Récupérer le nom des variables en argument d’une fonction
Il arrive qu’on ait envie de faire certaines choses en PHP et qu’on ne sache pas comment faire. On n’a pas envie de réinventer la roue, on va donc directement chez notre ami Google voir s’il a une réponse.
En PHP, on peut pratiquement tout faire, mais il arrive tout de même que certaines choses n’existent pas. D’où mon problème.
C’est ainsi que pour mon projet EasyDebug, j’ai eu besoin de récupérer le nom des variables qu’on passe en paramètre d’une fonction. Bien entendu j’ai lu partout que ce n’était pas possible et bien sûr les seuls exemples trouvés sur le net étaient peu concluants et me voilà bloqué dans mon élan.
Je suis donc parti a la recherche des éléments qui me permettrait de faire ce que je recherche si bien sûr c’était possible.
Un de mes problèmes était de trouver une technique qui me permette de trouver ce qu’on lui passe en paramètre simplement. Ce que je voulais c’était la simplicité et rapidité. Certain auraient pu par exemple résoudre mon problème en quelques secondes en ayant par exemple deux paramètres: ce qu’on lui passe genre une variable qui contient un array, un texte… et un second paramètre qui contienne le nom de notre variable.
Exemple:
<?php function trouve_parametre_2($param, $nom_param) { return "La variable `\$".$nom_param."` contient `".$param."`<br>\n"; } $un_texte = "C'est un test"; echo trouve_parametre_2($un_texte, "un_texte"); $une_date = "2014-01-10 10:00:00"; echo trouve_parametre_2($une_date, "une_date"); ?>
Bien sûr, ça ne va pas du tout autrement on ne se casserait pas la tête si c’était aussi simple et surtout notre fonction ne pourrait pas utiliser le multi paramètres. C’est ainsi que je me suis dit: on va-tout simplement aller chercher ce qu’on cherche directement ou ça existe c’est-à-dire dans le fichier ou on la écrit.
La fonction file()
Pour cela on va utiliser la fonction file() qui permet de lire un fichier. Elle nous sera utile et même la plus importante.
Le problème c’est que si on utilise notre fonction dans le fichier principal de notre code on aura aucun problème, mais comment faire si on l’utilise dans un fichier inclus dans le fichier principal ? Et surtout comment trouver son nom ?
La fonction debug_backtrace()
Au début je faisais ma recherche dans le fichier principal en utilisant $_SERVER[‘SCRIPT_FILENAME’], ce qui faisait que la fonction marchait seulement si on l’utilisait dans le fichier principal de notre code. Je n’étais donc pas satisfait.
Heureusement, la fonction debug_backtrace() résout tous nos problèmes. Cette fonction donne beaucoup d’information sur la fonction ou on l’utilise comme la ligne ou on l’appelle, mais surtout l’emplacement du fichier, ainsi on connait toujours le nom du fichier ou on utilise notre fonction.
Exemple:
On peut voir que la fonction utilisation_de_debug_backtrace() est utilsé la première fois dans le fichier `index.php` puis dans le fichier `fichier_inclus.php` qui est inclus dans le fichier `index.php`, bingo.
On a tout ce qu’on veut maintenant.
La fonction:
<?php function trouve_parametre($debug_backtrace) { foreach (debug_backtrace() as $key => $value) // Pour être sur que l'on trouve ce que l'on cherche { $function = $value['function']; // Nom de la fonction passé en paramètre, comme ça si on change le nom de la fonction( trouve_parametre() ) ça marche quand même $file_name = $value['file']; // nom du fichier ou est exécuté la fonction $ligne = $value['line']; // N° de ligne ou est exécuté la fonction $file = file($file_name); // On ouvre le fichier ou est exécuté la fonction $code_ligne = $file[$ligne-1]; // On récuèpère la ligne ou est exécuté la fonction, -1, car un fichier commence sur la ligne 0 $donnees = ""; if( in_array($function, array("require_once", "require", "include_once", "include"))) // On regarde si il y a un fichier inclut, si c'est le cas on est pas au bon endroit { // Il y a un fichier inclut, donc on s'en fous, mais ça n'arrive jamais... } else { if(preg_match_all('`'.$function.'\((.*?)\)`Uis', $code_ligne, $match, PREG_SET_ORDER) OR preg_match_all('`'.$function.' \((.*?)\)`Uis', $code_ligne, $match, PREG_SET_ORDER) ) // On recherche ce que la fonction a en paramètre { $nom_variable = trim($match[0][1]); // On enlève les espaces au début et a la fin if($nom_variable{0} == "$") // On compare le premier caractère { $donnees .= $nom_variable; } else // Ce n'est pas une variable { } } else // Si on passe en paramètre autre chose comme par exemple directement un array { } return $donnees; } } } ?>
Exemple d’utilsation:
<?php $variable = "C'est une variable"; echo trouve_parametre($variable).'<br>\n'; // La fonction va retourner: $variable echo trouve_parametre(array("Ce n'est une variable"))."<br>"; // La fonction va rien retourner, ce n'est pas une variable ?>
Comment aller plus loin:
Crée une petite class debug pour y utiliser notre fonction. Il faudra juste transmettre a la fonction ce que retourne debug_backtrace(). La transmission a toute son importance pour savoir l’emplacement exacte ou est exécuté notre class autrement on aura pas l’endroit réèle ou on appelle notre fonction et le debugage en sera plus compliqué.
Pour l’améliorer encore, on peut aussi identifier chaque paramètre si il y en a plusieurs et les récupérer…
Je vous laisse tester maintenant.
Tous les codes sont testés et sont fonctionnels, si il arrive qu'un de ces codes ne fonctionne pas chez vous, merci de me le signaler.