Comunitatea PHP Romania
MightyDeals

Prima pagină PHP General PHP Incepători functie apelant

functie apelant

Secţiune dedicată începatorilor.

Mesaj Vin Iun 01, 2012 9:39 pm
trey PHPRomania Supporter

Mesaje: 6
Salut

Caut o modalitate de a construi un fel de functie apelant care sa o folosesc la apelarea oricarei functii definite de utilizator cu un numar variabil de parametrii. Poate ca este inutil dar poate e si o solutie. Eu nu reusesc sa dau de ea. Nu astept un raspuns gen "foloseste un array ca sa nu mai ai nr variabil de parametrii". Am reusit ceva cu aplicabilitate limitata cu eval - nu merge cu orice tip de parametru. Cu array-uri ca parametrii de exemplu nu functioneaza cu eval... din ce am gasit eu.
Mai detaliat:

function Apelant ($nume){
// aici trebuie sa apeleze o functie, de exemplu cu numele
// foo primit prin $nume
foo ($a, $b, $c);
}

si apelul:

Apelant('foo', $a, $b, $c);

Am luat parametrii cu func_get_args() in definitia lui Apelant, dar mai departe nu gasesc o cale de a construi apelul.

Multumesc!


Mesaj Sâm Iun 02, 2012 9:04 am
MihaiC Avatar utilizator
Senior Member

Mesaje: 1600
Localitate: Navodari
Eu cred ca as folosi eval

   function Apelant() {
      $params = func_get_args();
      if (isset($params[0])) {
         $eval = $params[0] . '(';
         unset($params[0]);
         if (!empty($params)) {
            for ($i = 1;$i <= count($params);$i++) {
               $eval .= var_export($params[$i], 1);
               if ($i != count($params)) { $eval .= ', '; }
            }
         }
         $eval .= ');';
         eval($eval);
      }
   }
   
   Apelant('var_dump', array(1), 2, 3);
Internet Explorer – The Number one Browser For Downloading a Better Browser

Mesaj Sâm Iun 02, 2012 1:03 pm
trey PHPRomania Supporter

Mesaje: 6
Multumesc, asta nu foloseam eu ca sa mearga: var_export.

Totusi (sper sa nu gresesc) var_export nu pastreaza referinta la array-uri.
Ar pastra referinta serialize, dar array-ul meu contine closures care nu pot
fi serializate :(
Si deja am facut un compromis sa folosesc eval dar cu eval mai rau se
complica. Fara eval ar merge? Si fara oop (cu exceptia obiectelor closures).
E destul de ciudat ce vreau eu, recunosc, dar daca exista o solutie aici cred
ca o pot gasi. Sau macar aflu ca nu se poate.

Mesaj Sâm Iun 02, 2012 1:29 pm
MihaiC Avatar utilizator
Senior Member

Mesaje: 1600
Localitate: Navodari
si totusi, mi-am adus aminte ca exista deja functia ta

http://www.php.net/manual/en/function.c ... r-func.php
Internet Explorer – The Number one Browser For Downloading a Better Browser

Mesaj Lun Iun 04, 2012 10:32 am
trey PHPRomania Supporter

Mesaje: 6
MihaiC scrie:
si totusi, mi-am adus aminte ca exista deja functia ta


Multumesc, bine de stiut de functia asta. Dar ea nu imi pastreaza referita ...
Nu am pus problema foarte exact de la inceput dar e ok pentru ca am mai aflat cate ceva. Pe parcurs s-au desprins niste "probleme" de care nu mi-am dat seama de la inceput ca pot exista.

Eu am nevoie de o functie apelant care sa nu piarda referintele parametrilor functiilor pe care le va apela si care asteapta parametrii prin referinta. In plus, unii parametrii ai acestor functii sunt array-uri care contin closures. Nici closures nu ar trebui sa se piarda (cum se intampla daca folosesc var_export; serialize nu-i poate serializa).

O functie Apelant tot va trebui sa creez pentru ca se va apela o anumita functie in functie de niste conditii pe care call_user_func nu le cunoaste si nu tine cont. Sa folosesc call_user_func in definitia lui Apelant conduce la aceeasi problema de scriere a parametrilor in apel dinamic.

Mesaj Lun Iun 04, 2012 1:20 pm
MihaiC Avatar utilizator
Senior Member

Mesaje: 1600
Localitate: Navodari
Ok, faza la acest cod e ca da "Call-time pass-by-reference has been deprecated" pe php 5.3+
Ai putea incerca o solutie mai simpla cu call_user_func_array

   function increment(&$var) {
      ++$var;
   }
   
   function Apelant() {
      $stack = debug_backtrace();
      if (isset($stack[0]['args'][0])) {
         $ref = new ReflectionFunction($stack[0]['args'][0]);
         $i = 1;
         $args = array();
         foreach ($ref->getParameters() as $par) {
            if ($par->isPassedByReference()) {
               $args[] = &$stack[0]['args'][$i];
            } else {
               $args[] = $stack[0]['args'][$i];
            }
            $i++;
         }
         $ref->invokeArgs($args);
      }
   }
   
   $var = 1;
   Apelant('increment', &$var);
   echo $var;
Internet Explorer – The Number one Browser For Downloading a Better Browser

Mesaj Lun Iun 04, 2012 7:25 pm
trey PHPRomania Supporter

Mesaje: 6
Nu, trebuie să meargă fără să schinb ceva prin php.ini ca să permită scrierea
referinţei în apel. Şi fără OOP. Da, cam multe restricţii :)
call_user_func_array păstrează referinţa doar pentru versiuni PHP de
dinainte de 5.4. Altfel er fi fost exact ce-mi trebuia în definiţia lui Apelant.
Pe scurt e cam aşa:
Un array $arr şi un grup de funcţii care operează modificări pe acest array.
$arr posibil să conţină şi closures.
Fiecare funcţie din acest grup primeşte ca prim parametru pe $arr prin referinţă.
Restul parametrilor dacă există depind de fiecare funcţie din grup în parte.
Apelul ar fi cam aşa:
Apelant($arr, 'nume_func', $param1, ...);

Până la urmă dacă în php procedural nu e posibil ce vreau rămân la "soluţia" mea:
un switch case în definiţia lui Apelant şi apelul construit pe rând în funcţie de
parametrii primiţi. Doar nu vor fi zeci de parametrii. În caz că Apelant primeşte
mai multi parametrii decât poate gestiona, mai adaug ramuri case. E o glumă
de cod aşa cum zic eu dar e şi mai putin riscant - fără eval.

Mesaj Dum Apr 14, 2013 12:55 am
Google Bot New Member

Mesaje: 1

Înapoi la PHP Incepători

Copyright © 2001-2013 PHP Romania Gazduire web | Haine online | Gazduire web | Campanii SMS | Gazduire Claus Web | Inregistrare Domenii | Anunturi | Jocuri cu bile
Furnizat de phpBB® Forum Software © phpBB Group
Translation/Traducere: phpBB România
Powered by Simplis
cron