it-swarm.com.de

Wie bekomme ich einen Variablennamen als String in PHP?

Angenommen, ich habe diesen PHP Code:

$FooBar = "a string";

ich brauche dann eine Funktion wie diese:

print_var_name($FooBar);

welche druckt:

FooBar

Irgendwelche Ideen, wie man das erreichen kann? Ist das überhaupt in PHP möglich?

180
Gary Willoughby

Sie können get_defined_vars () verwenden, um den Namen einer Variablen zu finden, die denselben Wert hat wie die, deren Name Sie suchen. Natürlich wird dies nicht immer funktionieren, da verschiedene Variablen oft die gleichen Werte haben. Dies ist jedoch die einzige Möglichkeit, die mir dabei einfällt.

Edit: get_defined_vars () scheint nicht richtig zu funktionieren, es gibt 'var' zurück, da $ var in der Funktion selbst verwendet wird. $ GLOBALS scheint zu funktionieren, also habe ich es geändert.

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

    return false;
}

Edit: Um es klar zu sagen, gibt es keine gute Möglichkeit, dies in PHP zu tun, was wahrscheinlich daran liegt, dass Sie es nicht tun sollten. Es gibt wahrscheinlich bessere Möglichkeiten, das zu tun, was Sie versuchen.

36
Jeremy Ruten

Ich konnte mir keinen Weg vorstellen, dies effizient zu tun, aber ich kam dazu. Es funktioniert für die unten beschriebenen begrenzten Zwecke. 

Achselzucken

<?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
)

Sie basiert auf der Zeile, in der die Funktion aufgerufen wurde, und findet das Argument, das Sie eingegeben haben. Ich denke, es könnte erweitert werden, um mit mehreren Argumenten zu arbeiten. Wenn Sie die Situation jedoch besser erklären könnten, wäre eine andere Lösung wahrscheinlich arbeite besser.

42
Nick Presta

Vielleicht möchten Sie Ihren Ansatz ändern und einen variablen Variablennamen verwenden?

$var_name = "FooBar";
$$var_name = "a string";

dann könntest du einfach 

print($var_name);

bekommen 

FooBar

Hier ist der Link zum PHP Handbuch zu Variablenvariablen

25
John Satta

Niemand scheint die fundamentalen Gründe genannt zu haben warum das ist a) schwer und b) unklug:

  • Eine "Variable" ist nur ein Symbol, das auf etwas anderes zeigt. In PHP verweist es intern auf etwas namens "zval", das tatsächlich für mehrere Variablen gleichzeitig verwendet werden kann, entweder weil sie denselben Wert haben (PHP implementiert etwas namens "copy-on-write", so dass $foo = $bar muss nicht sofort zusätzlichen Speicher zuweisen) oder weil sie per Referenz zugewiesen (oder an eine Funktion übergeben) wurden (z. B. $foo =& $bar). Ein zval hat also keinen Namen.
  • Wenn Sie einen Parameter an eine Funktion übergeben, erstellen Sie eine neue Variable (auch wenn es sich um eine Referenz handelt). Sie könnten etwas anonymes übergeben, wie "hello", aber sobald Sie in Ihrer Funktion sind, ist es die Variable, als die Sie sie benennen. Dies ist ziemlich grundlegend für die Codetrennung: Wenn sich eine Funktion darauf stützt, welche Variable verwendet aufgerufen werden soll, ähnelt sie eher einer goto als einer ordnungsgemäß getrennten Funktion.
  • Globale Variablen werden im Allgemeinen als schlechte Idee angesehen. In vielen Beispielen wird davon ausgegangen, dass die Variable, die Sie "widerspiegeln" möchten, in $GLOBALS enthalten ist. Dies gilt jedoch nur, wenn Sie Ihren Code schlecht strukturiert haben und Variablen keinen Funktions- oder Funktionsumfang haben Objekt.
  • Variablennamen helfen Programmierern, ihren Code zu lesen. Das Umbenennen von Variablen, um sie ihrem Zweck besser anzupassen, ist eine weit verbreitete Umgestaltungspraxis, und der springende Punkt ist, dass es keinen Unterschied macht.

Jetzt verstehe ich den Wunsch nach Debugging (obwohl einige der vorgeschlagenen Verwendungen weit darüber hinausgehen), aber als verallgemeinerte Lösung ist es nicht so hilfreich, wie Sie vielleicht denken: Wenn Ihre Debug-Funktion sagt, dass Ihre Variable "$ file" heißt ", das kann immer noch eine von Dutzenden" $ file "-Variablen in Ihrem Code sein, oder eine Variable, die Sie" $ filename "genannt haben, aber an eine Funktion übergeben, deren Parameter" $ file "heißt.

Eine weitaus nützlichere Information ist, woher in Ihrem Code die Debug-Funktion aufgerufen wurde. Da Sie dies in Ihrem Editor schnell finden, können Sie sehen, welche Variable Sie für sich selbst ausgegeben haben, und sogar ganze Ausdrücke auf einmal übergeben (z. B. debug('$foo + $bar = ' . ($foo + $bar))).

Dafür können Sie dieses Snippet oben in Ihrer Debug-Funktion verwenden:

$backtrace = debug_backtrace();
echo '# Debug function called from ' . $backtrace[0]['file'] . ' at line ' . $backtrace[0]['line'];
18
IMSoP

Ich habe aus Debugging-Gründen eine Inspektionsfunktion erstellt. Es ist wie bei print_r () bei Steroiden, ähnlich wie bei Krumo, aber bei Objekten etwas effektiver. Ich wollte die Var-Namenserkennung hinzufügen und kam dazu, inspiriert von Nick Prestas Post auf dieser Seite. Es erkennt jeden Ausdruck, der als Argument übergeben wird, nicht nur Variablennamen. 

Dies ist nur die Wrapper-Funktion, die den übergebenen Ausdruck erkennt. __ In den meisten Fällen funktioniert dies. Es funktioniert nicht, wenn Sie die Funktion mehrmals in derselben Codezeile aufrufen.

Das funktioniert gut: die (inspect ( $ this-> getUser () -> hasCredential ("delete") ));

inspect () ist die Funktion, die den übergebenen Ausdruck erkennt.

Wir erhalten: $ this-> getUser () -> hasCredential ("delete")

function inspect($label, $value = "__undefin_e_d__")
{
    if($value == "__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.
        */

        $value = $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);

}

Hier ist ein Beispiel für die Inspector-Funktion (und meine dInspect-Klasse) in Aktion:

http://inspect.ip1.cc

Die Texte sind auf dieser Seite in spanischer Sprache, aber der Code ist kurz und einfach zu verstehen.

13

Lucas auf PHP.net bot eine zuverlässige Möglichkeit, um zu überprüfen, ob eine Variable existiert. In diesem Beispiel durchläuft er eine Kopie des Arrays der globalen Variablen (oder eines Bereichs mit Variablen), ändert den Wert in einen zufällig generierten Wert und prüft den erzeugten Wert im kopierten Array. 

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;
}

Dann versuche es:

$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

Bitte überprüfe seinen Beitrag auf PHP.net: http://php.net/manual/de/language.variables.php

9
Workman

Das ist genau das, was Sie wollen - es ist eine gebrauchsfertige Funktion zum Kopieren und Ablegen, die den Namen einer gegebenen Var wiedergibt:

function print_var_name(){
    // read backtrace
    $bt   = debug_backtrace();
    // read file
    $file = file($bt[0]['file']);
    // select exact print_var_name($varname) line
    $src  = $file[$bt[0]['line']-1];
    // search pattern
    $pat = '#(.*)'.__FUNCTION__.' *?\( *?(.*) *?\)(.*)#i';
    // extract $varname from match no 2
    $var  = preg_replace($pat, '$2', $src);
    // print to browser
    echo trim($var);
}

VERWENDUNG: print_var_name ($ FooBar)

DRUCKEN: FooBar

HINWEIS Jetzt können Sie die Funktion umbenennen und sie wird weiterhin funktionieren und die Funktion auch mehrmals in einer Zeile verwenden! Danke an @Cliffordlife

6
adilbo

Von php.net

@Alexandre - kurze Lösung

<?php
function vname(&$var, $scope=0)
{
    $old = $var;
    if (($key = array_search($var = 'unique'.Rand().'value', !$scope ? $GLOBALS : $scope)) && $var = $old) return $key;  
}
?>

@ Lucas - Nutzung

<?php
//1.  Use of a variable contained in the global scope (default):
  $my_global_variable = "My global string.";
  echo vname($my_global_variable); // Outputs:  my_global_variable

//2.  Use of a local variable:
  function my_local_func()
  {
    $my_local_variable = "My local string.";
    return vname($my_local_variable, get_defined_vars());
  }
  echo my_local_func(); // Outputs: my_local_variable

//3.  Use of an object property:
  class myclass
  {
    public function __constructor()
    {
      $this->my_object_property = "My object property  string.";
    }
  }
  $obj = new myclass;
  echo vname($obj->my_object_property, $obj); // Outputs: my_object_property
?>
5
user669677

Viele Antworten stellen die Nützlichkeit dieser Frage in Frage. Eine Referenz für eine Variable zu erhalten, kann jedoch sehr nützlich sein. Besonders in Fällen mit Objekten und $ this . Meine Lösung arbeitet mit Objekten und auch als Eigenschaft definierte Objekte:

function getReference(&$var)
{
    if(is_object($var))
        $var->___uniqid = uniqid();
    else
        $var = serialize($var);
    $name = getReference_traverse($var,$GLOBALS);
    if(is_object($var))
        unset($var->___uniqid);
    else
        $var = unserialize($var);
    return "\${$name}";    
}

function getReference_traverse(&$var,$arr)
{
    if($name = array_search($var,$arr,true))
        return "{$name}";
    foreach($arr as $key=>$value)
        if(is_object($value))
            if($name = getReference_traverse($var,get_object_vars($value)))
                return "{$key}->{$name}";
}

Beispiel für das Obige:

class A
{
    public function whatIs()
    {
        echo getReference($this);
    }
}

$B = 12;
$C = 12;
$D = new A;

echo getReference($B)."<br/>"; //$B
echo getReference($C)."<br/>"; //$C
$D->whatIs(); //$D
4
K. Brunner

Aus den obigen Antworten für viele Variablen mit guter Leistung angepasst, für viele nur ein $ GLOBALS-Scan

function compact_assoc(&$v1='__undefined__', &$v2='__undefined__',&$v3='__undefined__',&$v4='__undefined__',&$v5='__undefined__',&$v6='__undefined__',&$v7='__undefined__',&$v8='__undefined__',&$v9='__undefined__',&$v10='__undefined__',&$v11='__undefined__',&$v12='__undefined__',&$v13='__undefined__',&$v14='__undefined__',&$v15='__undefined__',&$v16='__undefined__',&$v17='__undefined__',&$v18='__undefined__',&$v19='__undefined__'
) {
    $defined_vars=get_defined_vars();

    $result=Array();
    $reverse_key=Array();
    $original_value=Array();
    foreach( $defined_vars as $source_key => $source_value){
        if($source_value==='__undefined__') break;
        $original_value[$source_key]=$$source_key;
        $new_test_value="PREFIX".Rand()."SUFIX";
        $reverse_key[$new_test_value]=$source_key;
        $$source_key=$new_test_value;

    }
    foreach($GLOBALS as $key => &$value){
        if( is_string($value) && isset($reverse_key[$value])  ) {
            $result[$key]=&$value;
        }
    }
    foreach( $original_value as $source_key => $original_value){
        $$source_key=$original_value;
    }
    return $result;
}


$a = 'A';
$b = 'B';
$c = '999';
$myArray=Array ('id'=>'id123','name'=>'Foo');
print_r(compact_assoc($a,$b,$c,$myArray) );

//print
Array
(
    [a] => A
    [b] => B
    [c] => 999
    [myArray] => Array
        (
            [id] => id123
            [name] => Foo
        )

)
2
user1933288

Wenn die Variable austauschbar ist, müssen Sie irgendwo eine Logik haben , die bestimmt, welche Variable verwendet wird. Alles, was Sie tun müssen, ist, den Variablennamen in $variable innerhalb dieser Logik einzufügen, während Sie alles andere tun.

Ich denke, es fällt uns allen schwer zu verstehen, wofür Sie das brauchen. Beispielcode oder eine Erklärung dessen, was Sie tatsächlich versuchen zu tun , könnte helfen, aber ich vermute, Sie sind so, so = das überdenken.

1
ceejayoz

Ich habe das:

  debug_echo(array('$query'=>$query, '$nrUsers'=>$nrUsers, '$hdr'=>$hdr));

Ich würde es vorziehen:

  debug_echo($query, $nrUsers, $hdr);

Die vorhandene Funktion zeigt ein gelbes Feld mit einer roten Umrandung an und zeigt jede Variable nach Namen und Wert an. Die Array-Lösung funktioniert, ist jedoch etwas kompliziert, wenn sie benötigt wird.

Das ist mein Anwendungsfall und ja, das hat mit dem Debuggen zu tun. Ich stimme denjenigen zu, die ihre Verwendung anderweitig in Frage stellen.

1
Will Fastie

Ich habe tatsächlich einen gültigen Anwendungsfall dafür.

Ich habe eine Funktion cacheVariable ($ var) (ok, ich habe einen Funktionscache ($ key, $ value), aber ich hätte gerne eine Funktion wie erwähnt).

Der Zweck ist zu tun:

$colour = 'blue';
cacheVariable($colour);

...

// another session

...

$myColour = getCachedVariable('colour');

Ich habe es mit versucht 

function cacheVariable($variable) {
   $key = ${$variable}; // This doesn't help! It only gives 'variable'.
   // do some caching using suitable backend such as apc, memcache or ramdisk
}

Ich habe es auch mit probiert

function varName(&$var) {
   $definedVariables = get_defined_vars();
   $copyOfDefinedVariables = array();
   foreach ($definedVariables as $variable=>$value) {
      $copyOfDefinedVariables[$variable] = $value;
   }
   $oldVar = $var;
   $var = !$var;
   $difference = array_diff_assoc($definedVariables, $copyOfDefinedVariables);
   $var = $oldVar;
   return key(array_slice($difference, 0, 1, true));
}

Das scheitert aber auch ... :(

Klar, ich könnte weiterhin Cache machen ('color', $ color), aber ich bin faul, weißt du ...;)

Was ich also will, ist eine Funktion, die den ORIGINAL-Namen einer Variablen erhält, da sie an eine Funktion übergeben wurde. Innerhalb der Funktion gibt es keine Möglichkeit, das zu wissen, wie es scheint. Die Übergabe von get_defined_vars () als Referenz im zweiten Beispiel oben hat mir (Danke an Jean-Jacques Guegan für diese Idee) etwas geholfen. Die letztere Funktion funktionierte zwar, gab jedoch immer nur die lokale Variable zurück ('variable', nicht 'color'). 

Ich habe noch nicht versucht, get_func_args () und get_func_arg (), $ {} - Konstrukte und key () kombiniert zu verwenden, aber ich gehe davon aus, dass dies ebenfalls fehlschlagen wird.

1
Aron Cederholm

Hier ist meine Lösung basierend auf Jeremy Ruten

class DebugHelper {

    function printVarNames($systemDefinedVars, $varNames) {
        foreach ($systemDefinedVars as $var=>$value) {
            if (in_array($var, $varNames )) {
                var_dump($var);
                var_dump($value);
            }
        }
    }
}

es benutzen

DebugHelper::printVarNames(
    $systemDefinedVars = get_defined_vars(),
    $varNames=array('yourVar00', 'yourVar01')
);
0
dakiquang

Ich denke, Sie möchten den Variablennamen mit seinem Wert kennen. Sie können dazu ein assoziatives Array verwenden.

verwenden Sie Variablennamen für Array-Schlüssel:

$vars = array('FooBar' => 'a string');

Wenn Sie Variablennamen abrufen möchten, verwenden Sie array_keys($vars). Es wird ein Array der Variablennamen zurückgegeben, die in Ihrem $vars-Array als Schlüssel verwendet werden.

0

Warum bauen Sie nicht einfach eine einfache Funktion und erzählen es?

/**
 * Prints out $obj for debug
 *
 * @param any_type $obj
 * @param (string) $title
 */
function print_all( $obj, $title = false )
{
    print "\n<div style=\"font-family:Arial;\">\n";
    if( $title ) print "<div style=\"background-color:red; color:white; font-size:16px; font-weight:bold; margin:0; padding:10px; text-align:center;\">$title</div>\n";
    print "<pre style=\"background-color:yellow; border:2px solid red; color:black; margin:0; padding:10px;\">\n\n";
    var_export( $obj );
    print "\n\n</pre>\n</div>\n";
}

print_all( $aUser, '$aUser' );
0
AnOldMan

Ich suchte das, entschied mich aber gerade, den Namen weiterzugeben. Normalerweise habe ich den Namen in der Zwischenablage.

function VarTest($my_var,$my_var_name){
    echo '$'.$my_var_name.': '.$my_var.'<br />';
}

$fruit='Apple';
VarTest($fruit,'fruit');
0
Kieron Axten

Um dies zu erreichen, können Sie compact () verwenden.

$FooBar = "a string";

$newArray = compact('FooBar');

Dadurch würde ein assoziatives Array mit dem Variablennamen als Schlüssel erstellt. Sie können dann das Array mit dem Schlüsselnamen an der gewünschten Stelle durchlaufen.

foreach($newarray as $key => $value) {
    echo $key;
}
0
Budove