217 votes

Comment obtenir un nom de variable sous forme de chaîne en PHP?

Disons que j'ai ce code PHP:

 $FooBar = "a string";
 

J'ai alors besoin d'une fonction comme celle-ci:

 print_var_name($FooBar);
 

qui imprime:

 FooBar
 

Des idées pour y parvenir? Est-ce même possible en PHP?

53voto

Nick Presta Points 13298

Je ne pouvais pas penser à un moyen de le faire efficacement non plus, mais je suis arrivé à cela. Cela fonctionne, pour les utilisations limitées ci-dessous.

hausser les épaules

 <?php

function varName( $v ) {
    $trace = debug_backtrace();
    $vLine = file( __FILE__ );
    $fLine = $vLine[ $trace[0]['line'] - 1 ];
    preg_match( "#\\$(\w+)#", $fLine, $match );
    print_r( $match );
}

$foo = "knight";
$bar = array( 1, 2, 3 );
$baz = 12345;

varName( $foo );
varName( $bar );
varName( $baz );

?>

// Returns
Array
(
    [0] => $foo
    [1] => foo
)
Array
(
    [0] => $bar
    [1] => bar
)
Array
(
    [0] => $baz
    [1] => baz
)
 

Il fonctionne en fonction de la ligne qui a appelé la fonction, où il trouve l'argument que vous avez transmis. Je suppose qu'il pourrait être étendu pour fonctionner avec plusieurs arguments mais, comme d'autres l'ont déjà dit, une autre solution serait probablement mieux travailler.

46voto

Jeremy Ruten Points 59989

Vous pouvez utiliser get_defined_vars() pour trouver le nom d'une variable qui a la même valeur que celui que vous essayez de trouver le nom de. Évidemment, cela ne fonctionne pas toujours, puisque les différentes variables ont souvent les mêmes valeurs, mais c'est la seule façon que je peux penser à le faire.

Edit: get_defined_vars() ne semble pas fonctionner correctement, il renvoie 'var' parce que $var est utilisé dans la fonction elle-même. $GLOBALS semble fonctionner alors je l'ai changé.

function print_var_name($var) {
    foreach($GLOBALS as $var_name => $value) {
        if ($value === $var) {
            return $var_name;
        }
    }

    return false;
}

Edit: pour être clair, il n'y a pas de bonne façon de le faire en PHP, qui est probablement parce que vous ne devriez pas avoir à le faire. Il y a probablement de meilleures façons de faire ce que vous essayez de faire.

15voto

J'ai fait une fonction d'inspection pour des raisons de débogage. C'est comme print_r() sur les stéroïdes, à l'instar de Krumo mais un peu plus efficace sur les objets. Je voulais ajouter le var nom de la détection et, avec cela, inspirée par Nick Presta post sur cette page. Il détecte toute expression passée en argument, non seulement les noms de variables.

Ce n'est que le wrapper fonction qui détecte le passé de l'expression. Fonctionne sur la plupart des cas. Il ne fonctionnera pas si vous appelez la fonction plus d'une fois dans la même ligne de code.

Cela fonctionne très bien: die(inspecter($this->getUser()->hasCredential("supprimer")));

inspecter() est la fonction qui permet de détecter le passé de l'expression.

On obtient: $this->getUser()->hasCredential("supprimer")

function inspect($label, $val = "__undefin_e_d__")
{
    if($val == "__undefin_e_d__") {

        /* The first argument is not the label but the 
           variable to inspect itself, so we need a label.
           Let's try to find out it's name by peeking at 
           the source code. 
        */

        /* The reason for using an exotic string like 
           "__undefin_e_d__" instead of NULL here is that 
           inspected variables can also be NULL and I want 
           to inspect them anyway.
        */

        $val = $label;

        $bt = debug_backtrace();
        $src = file($bt[0]["file"]);
        $line = $src[ $bt[0]['line'] - 1 ];

        // let's match the function call and the last closing bracket
        preg_match( "#inspect\((.+)\)#", $line, $match );

        /* let's count brackets to see how many of them actually belongs 
           to the var name
           Eg:   die(inspect($this->getUser()->hasCredential("delete")));
                  We want:   $this->getUser()->hasCredential("delete")
        */
        $max = strlen($match[1]);
        $varname = "";
        $c = 0;
        for($i = 0; $i < $max; $i++){
            if(     $match[1]{$i} == "(" ) $c++;
            elseif( $match[1]{$i} == ")" ) $c--;
            if($c < 0) break;
            $varname .=  $match[1]{$i};
        }
        $label = $varname;
    }

    // $label now holds the name of the passed variable ($ included)
    // Eg:   inspect($hello) 
    //             => $label = "$hello"
    // or the whole expression evaluated
    // Eg:   inspect($this->getUser()->hasCredential("delete"))
    //             => $label = "$this->getUser()->hasCredential(\"delete\")"

    // now the actual function call to the inspector method, 
    // passing the var name as the label:

      // return dInspect::dump($label, $val);
         // UPDATE: I commented this line because people got confused about 
         // the dInspect class, wich has nothing to do with the issue here.

    echo("The label is: ".$label);
    echo("The value is: ".$value);

}

Voici un exemple de l'inspecteur de la fonction (et mon dInspect classe) en action:

http://inspect.jaku.com.ar

Les textes sont en espagnol dans cette page, mais le code est concis et très facile à comprendre.

14voto

Workman Points 583

Lucas PHP.net pourvu d'un moyen fiable de vérifier si une variable existe. Dans son exemple, il parcourt une copie de la variable globale tableau (ou une étendue array) de variables, les changements de la valeur à une valeur générée de façon aléatoire, et vérifie la valeur générée dans la copie de ce tableau.

function variable_name( &$var, $scope=false, $prefix='UNIQUE', $suffix='VARIABLE' ){
    if($scope) {
        $vals = $scope;
    } else {
        $vals = $GLOBALS;
    }
    $old = $var;
    $var = $new = $prefix.rand().$suffix;
    $vname = FALSE;
    foreach($vals as $key => $val) {
        if($val === $new) $vname = $key;
    }
    $var = $old;
    return $vname;
}

Essayez:

$a = 'asdf';
$b = 'asdf';
$c = FALSE;
$d = FALSE;

echo variable_name($a); // a
echo variable_name($b); // b
echo variable_name($c); // c
echo variable_name($d); // d

Assurez-vous de vérifier son post sur PHP.net: http://php.net/manual/en/language.variables.php

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X