J'ecris ce petit article car je n'ai pas trouvé sur le site de php de documentation
sur le passage de pointeur de fonction à une autres fonctions ou méthodes d'un object.
Je savais pourtant qu'il etait possible de réaliser cela en l'ayant vu dans un source php.
Cependant il y a la fonction: call_user_func -- Call a user function given by the first parameter documentée sur le site de php.
Le terme de pointeur de fonction est erroné dans cette article, j'espere que vous ne prendrez pas la mouche pour cette abu de langage.
Donc je debute a chercher comment faire et me dis que je vais tenter au plus simple, et en fait cela marche. Voici l'exemple:
function toto ( ) { echo "toto"; } function tutu ( $pfunc ) { for ($i=0;$i<5;$i++) $pfunc( ); } tutu(toto);Et donc j'obtiens:
function toto ($s ) { echo "$s "; } function tutu ( $pfunc ) { for ($i=0;$i<5;$i++) $pfunc( "toto" ); } tutu(toto);Et meme traitement, meme chatiment :)
Heureux de voir que je n'ai pas de probleme, je regarde si cela marche aussi avec des objects. Je definit donc un object tete ( j'ai deja utilise les toto tutu :).
class tete { var $name; function tete($s) { $this->name=$s; } function tutu($pfunc) { for ($i=0;$i<5;$i++) $pfunc( $this->name ); } function toto() { echo "$this->nameEt je l'appelle par la suite.
" } }
function toto ( $s ) { echo "$s "; } $tete=new tete("toto"); echo "Appel de la methode tutu avec comme pointeur de fonction toto"; $tete->tutu(toto);La encore j'ai mes cinq toto ( plus un present dans le echo ).
function totowiththis() { echo "$this->name"; }He bien cela ne marche pas du tout coup , la force n'est pas avec moi et mon reve d'enfant est detruit :(.
function toto($obj) { echo "$obj->name"; }cinq toto, ce qui nous fait dix to,t,o soit cinquante caracteres :).
function toto($this) { echo "$this->name"; }
L'essai avec une methode s'impose, je ne pouvais pas reculer. Alors j'appelle la fonction tutu avec la methode toto.
tutu($tete->pfunction);Et la arggg, j'obtiens l'erreur php:
tutu("tete->pfunction");Ne marche pas non plus , et pour cause , il ne connait pas la variable tete, cependant en ajoutant la variable global $tete dans la fonction pas de probleme; mais la cela n'a aucun interet.
function tutu ($obj,$pfunc ) { for ($i=0;$i<5;$i++) $obj->$pfunc( "toto" ); } $tete=new tete("toto"); echo "Voila cette solution fonctionne.Et de meme dans l'appel dans l'objet s'effectue en ne passant que le nom de la methode.
***Objet et Methode *********
"; tutu($tete,"pfunction");
Bon, alors la c'est un peu space , mais comme me dirait mon ami pierre cela se tente :). La encore pas de grosse difficulte.
[ modifiez le constructeur de tete ] function tete($s) { $this->name=$s; echo "toto $s"; } function tutuconstruteur ($obj) { global $tete; for ($i=0;$i<5;$i++) $tab[$i]=new $obj("$i"); } tutuconstruteur("tete");Nous donne : toto 0
Bon, j'espere que ce petit article vous a interresse.
Les exemples en Live
Je suis d'accord qu'il est difficile de parler de pointeur de fonction alors cela que l'on passe est une
chaine de caractere.
Et me direz vous ce n'est pas si etonnant que cela marche car php est un langage interprete.
Ceci n'a rien d'etonnant avec d'autre langage comme le tcl par exemple.
Avec la fonction call_user_func on obtient les memes resultats lors de l'appel d'une fonction cependant
pour les objets je ne sais pas comment faire pour passer le $this ?
Mais me direz-vous que faire de pointeur de fonction alors que php ce veut un langage orienté objet.
Premierement c'est toujours interressant de connaitre les possibilitées du langage.
Sinon, si l'on a une classe mappant un objet d'un base de donnée mais que l'on veut extraire la representation
des donnée de l'objet de l'objet lui meme ( ce qui est d'pares moi une bonne chose ) on peut tout de
meme créer dans l'objet un iteration sur les raws et ecrire une fonction representant les donnees.
Exemple ( j'ai ecris cet exemple sans le tester reelement merci de m'excusez s'il y a des erreurs ):
class mapunetable extends class_basededonne { var $nom; var $prenom; // Constructeur function mapunetable() { $this->class_basededonne(); } function getnom() { return($nom);} function getprenom() { return($prenom);} [...] // On iterateur sur la base et on apelle une fonction function listpersonne($pfunc,$query) { $nb=$this->execute($query); for ($i=0; $i<$nb; $i++) { $resultsql = $this->get_next_row(); $this->getfrombd($tmp["idx"]); $pfunc($this); } } // On iterateur sur la base et on appelle une methode d'un objet function listpersonneOO($obj,$pfunc,$query) { $nb=$this->execute($query); for ($i=0; $i<$nb; $i++) { $resultsql = $this->get_next_row(); $this->getfrombd($tmp["idx"]); $obj->$pfunc($this); } } } [Dans un autre fichier fait par quelqu'un d'autre qui ne s'appele pas toto] function affpersonne($obj) { echo "$obj->getnom()
"; echo "$obj->getprenom()
"; } $m=new mapunetable() $m->listpersonne(affpersonne);
Sinon voici une autre utilisation possible:
Dans beaucoup de programme PHP on utilise une variable genre "operation" pour dire au scripte ce que l'on va faire.
Et bien au lieu de faire du gros switch case ( petit mais deviendra grand ;).On peut mettre simplement les nom cle de l'operation dans une
hastable relie a un nom de fonction. Exemple:
Au lieu de : switch ($op) { case "showsubcat" : [...] break; case "showobj" : [...] break; }Que pensez vous de cela:
function showsubcat() { [...] } function showobj() { [...] } $pfuncop=array("showsubcat"=>showsubcat, "showobj"=>showobj); ( teste pour verifier si op est presente et est dans le tableau $pfuncop ) $pfuncop["$op"]();
Un collegue m'a demande est-ce que cela marchera avec php4 ?
mais j'ignore la reponse , peut etre quelqu'un le sait-il ?
Avec php4, le langage se dote de nouvelles fonctionnalités comme get_class_methods et autres get_class_vars , get_object_vars ... permettant peut etre une introspection des objets et tout cela pour afficher du HTML :).