Wie bekomme ich einen Variablennamen als String in PHP?

200

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 erreicht? Ist das überhaupt in PHP möglich?

Gary Willoughby
quelle
9
Wenn Sie dies für etwas anderes als das Debuggen benötigen, machen Sie etwas schwerwiegendes falsch. Was ist Ihr Anwendungsfall?
Troelskn
9
Gute Frage. Ich brauchte das gleiche zum Debuggen.
Takeshin
17
+1 - Ich brauchte dies, um eine XML- oder JSON-Antwort von einem PHP-Modellobjekt automatisch zu generieren. Wenn Sie das Objekt in ein anderes benanntes rootName => modelObjectArray einschließen müssen, wird der Antwort nur unnötige Tiefe verliehen. Ich wünschte, dies wäre in die Laufzeitreflexionsfunktionen der Sprache integriert.
Anurag
4
Ich hatte dies auch in einer Protokollierungsfunktion benötigt. Ich wollte in der Lage sein, Folgendes zu tun: log ($ didTheSystemBlowUp); In der Protokolldatei wie folgt erscheinen: $ didTheSystemBlowUp = 'noch nicht, aber sehr bald';
SeanDowney
4
Dies kann auch nützlich sein, wenn Sie var_dump () aufrufen. Wenn Sie also mehrere Variablen gleichzeitig aufrufen, müssen Sie den Variablennamen nicht manuell ausgeben, um zwischen den Ausgaben von vardupms zu unterscheiden.
PHPst

Antworten:

37

Sie könnten get_defined_vars () verwenden , um den Namen einer Variablen zu ermitteln, die denselben Wert hat wie die, deren Namen . Natürlich wird dies nicht immer funktionieren, da verschiedene Variablen oft die gleichen Werte haben, aber es ist die einzige Möglichkeit, die ich mir vorstellen kann, dies zu tun.

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

Bearbeiten: Um klar zu sein, 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.

Jeremy Ruten
quelle
2
Ahh. War zu langsam ;-) Dachte das gleiche, aber benutze stattdessen $ GLOBALS. Der Identitätsvergleich ergibt also true für gleich skalare Werte ($ a = 'foo'; $ b = 'foo'; assert ($ a === $ b);)?
Argelbargel
Nachdem ich meinen Code getestet habe, gab mein Code immer 'var' zurück, da er in der Funktion verwendet wird. Wenn ich stattdessen $ GLOBALS verwende, wird aus irgendeinem Grund der richtige Variablenname zurückgegeben. Also werde ich den obigen Code ändern, um $ GLOBALS zu verwenden.
Jeremy Ruten
Ja, mir wurde klar, aber get_defined_vars () war genug ta.
Gary Willoughby
2
Es gibt viele Fälle, in denen sich dieser Code nicht wie erwartet verhält.
Troelskn
122
Dieser Code ist schrecklich falsch. Es ist eine sehr dumme Idee, zu überprüfen, ob die Variable mit der von VALUE gesendeten übereinstimmt. Myriaden von Variablen sind zu jedem Zeitpunkt NULL. Myriaden werden auf 1 gesetzt. Das ist einfach verrückt.
Alex Weinstein
49

Ich konnte mir auch keinen Weg vorstellen, dies effizient zu tun, aber ich habe mir das ausgedacht. Es funktioniert für die unten angegebenen begrenzten Verwendungszwecke.

zucken

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

Es funktioniert basierend auf der Zeile, die die Funktion aufgerufen hat, in der das von Ihnen übergebene Argument gefunden wird. Ich nehme an, es könnte erweitert werden, um mit mehreren Argumenten zu arbeiten, aber wie andere gesagt haben, würde es wahrscheinlich eine andere Lösung geben, wenn Sie die Situation besser erklären könnten arbeite besser.

Nick Presta
quelle
2
Dies funktioniert jedoch nur, wenn die Funktion varName in derselben Datei wie die zu findende Variable definiert ist.
Rubo77
1
Hier finden Sie eine bessere Implementierung, die über mehrere Includes funktioniert
rubo77
30

Sie könnten erwägen, Ihren Ansatz zu ändern und einen variablen Variablennamen zu 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


quelle
42
Ich habe mit einem System gearbeitet, das Variablenvariablen ausgiebig verwendete. Lass mich dich warnen, es stinkt sehr schnell!
Icode4food
3
In den meisten Fällen möchte der Benutzer den Namen und den Wert einer Variable erhalten. Denken Sie an "function debugvar ($ varname)" und er beabsichtigt, es "debugvar ('foo')" zu nennen, damit das Debug "foo = 123" anzeigt. mit variablen variablen erhalten sie 'foo' ist undefiniert.
GCB
Schau dir nur an, was du gerade machst. Genau dort in Ihrem Beispiel erstellen Sie tatsächlich eine Variable $FooBarmit dem Wert, den Sie a stringgerade in Ihrem Handbuch gelesen haben. Das ist schrecklich imho. Sie weisen der Variablen niemals $FooBareinen Wert zu, aber dieser ist vorhanden. AUTSCH
Toskan
20

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

  • Eine "Variable" ist nur ein Symbol, das auf etwas anderes zeigt. In PHP verweist es intern auf etwas, das als "zval" bezeichnet wird und tatsächlich für mehrere Variablen gleichzeitig verwendet werden kann, entweder weil sie denselben Wert haben (PHP implementiert etwas, das als "Copy-on-Write" bezeichnet wird, so dass $foo = $bardies nicht erforderlich ist zusätzlichen Speicher sofort zuweisen) oder weil sie durch Referenz zugewiesen (oder an eine Funktion übergeben) wurden (z $foo =& $bar. B. ). 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, "hello"aber sobald Sie sich in Ihrer Funktion befinden, ist es die Variable, als die Sie es bezeichnen. Dies ist für die Codetrennung ziemlich grundlegend: Wenn sich eine Funktion auf das stützt, was eine Variable früher aufgerufen hat, ist sie eher eine gotoals eine ordnungsgemäß getrennte Funktion.
  • Globale Variablen werden im Allgemeinen als schlechte Idee angesehen. In vielen Beispielen wird davon ausgegangen, dass die Variable, die Sie "reflektieren" möchten, in gefunden werden $GLOBALSkann. Dies gilt jedoch nur, wenn Sie Ihren Code schlecht strukturiert haben und Variablen nicht auf eine Funktion oder ein Objekt beschränkt sind.
  • Variablennamen helfen Programmierern beim Lesen ihres Codes. Das Umbenennen von Variablen, um sie besser an ihren Zweck anzupassen, ist eine weit verbreitete Refactoring-Praxis, 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 allgemeine Lösung ist es nicht so hilfreich, wie Sie vielleicht denken: Wenn Ihre Debug-Funktion besagt, dass Ihre Variable "$ file" heißt ", das kann immer noch eine von Dutzenden von" $ 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 schnell in Ihrem Editor finden, können Sie sehen, welche Variable Sie für sich selbst ausgegeben haben, und sogar ganze Ausdrücke auf einmal übergeben (zdebug('$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'];
IMSoP
quelle
Es gibt bereits einige gute Antworten. Das ist also selbst angesichts der Realität nur pessimistisch.
A20
@ a20 Alle Antworten haben große Einschränkungen, wann sie verwendet werden können und wann sie brechen werden. none ist eine einfache Suche von einer Variablen zu ihrem Namen, da dies tatsächlich unmöglich ist. Einige machen viel Funky Reflection für Debugging-Zwecke, was in Ordnung ist; Meiner Meinung nach ist es jedoch besser, wenn Sie nur die Zeilennummer ausgeben und die Quellzeile selbst nachschlagen - oder einen interaktiven Debugger wie XDebug verwenden.
IMSoP
14

Dies ist genau das, was Sie wollen - es ist eine gebrauchsfertige "Kopieren und Ablegen" -Funktion, die den Namen einer bestimmten Variablen 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

TIPP Jetzt können Sie die Funktion umbenennen und sie funktioniert weiterhin und wird auch mehrmals in einer Zeile verwendet! Vielen Dank an @Cliffordlife

Adilbo
quelle
3
Cool, danke dafür. Ich habe die $ pat-Zeile leicht so geändert $pat = '#(.*)'.__FUNCTION__.' *?\( *?(.*) *?\)(.*)#i';, dass es mir egal ist, wie diese Debug-Funktion heißt, und ich bekomme genau das, was an die Funktion übergeben wird, dh $ hello oder "hello" (ich habe die $ match für die übergebene Variable gelöscht in, in der gleichen Zeile)
Cliffordlife
1
Fantastischer Code! Vielen Dank! Es scheint jedoch nicht in allen Fällen zu funktionieren. Ergebnis des Testens auf meinem Ubuntu 18.04 mit PHP 7.2.19: Funktioniert nicht, wenn es mehrmals in derselben Codezeile verwendet wird, unabhängig davon, ob es in einem oder mehreren Ausdrücken verwendet wird, da es dann den Namen der letzten Variablen von zurückgibt Linie. Wenn es im selben Ausdruck, aber in separaten Zeilen verwendet wird, funktioniert es. Wird in verschiedenen Ausdrücken in verschiedenen Zeilen verwendet.
Matty
1
Auch diese Funktion sollte in einer Zeile ohne "var_dump" stehen - mit kombinierter print_var_name, echo, var_dumpSendeausgabe$variable); echo ' '; var_dump($variable
BG Bruno
13

Lucas auf PHP.net bot eine zuverlässige Möglichkeit, um zu überprüfen, ob eine Variable vorhanden ist. In seinem Beispiel durchläuft er eine Kopie des globalen Variablenarrays (oder eines Bereichsarrays) von Variablen, ändert den Wert in einen zufällig generierten Wert und überprüft den generierten 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

Überprüfen Sie unbedingt seinen Beitrag auf PHP.net: http://php.net/manual/en/language.variables.php

Arbeiter
quelle
Wie erhalten Sie den aktuellen Bereich in Array-Form?
Sebastián Grignoli
Nett! Für mich fehlt nur, break;wenn in foreach + gleich gefunden wird. Ich habe eine verwendbare Grundstruktur verwendet, um automatisch var_name zu erhalten, auch wenn diese innerhalb der Funktion definiert ist. Wenn Sie häufig kopieren und einfügen oder eine bessere Idee zur Verbesserung haben, verwenden Sievariable_name( $variable, ( empty(__FUNCTION__) ? false : get_defined_vars() ) );
odie2
Dies ist wahrscheinlich der schnellste und sauberste Weg, um die Arbeit zu erledigen. Das Debuggen beinhaltet wahrscheinlich Leistungsprobleme. Die Funktion sollte direkt in der foreach-Schleife zurückkehren, anstatt nur ohne Unterbrechung zuzuweisen. Angesichts der Tatsache, dass die GLOBALS groß sein können, kann dies eine erhebliche Leistungsverbesserung darstellen.
John
13

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

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

Das funktioniert gut: sterben ( inspizieren ($ 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 Inspektorfunktion (und meine dInspect-Klasse) in Aktion:

http://inspect.ip1.cc

Die Texte auf dieser Seite sind spanisch, aber der Code ist präzise und sehr leicht zu verstehen.

Sebastián Grignoli
quelle
1
ähm, hängt das nicht davon ab, dass Sie den NuSphare-Debugger installiert haben?
Mawg sagt, Monica am
Ich habe dort eine vereinfachte Version dieses Codes gepostet. Auch ich habe diese Antwort geändert. Es sollte jetzt auf jeder PHP5-Implementierung ausgeführt werden.
Sebastián Grignoli
Einfallsreichtum wie dieser ist der Grund, warum ich jedes Mal lächle, wenn ich sehe, dass Leute sagen "kann nicht gemacht werden" oder "nicht möglich", was in diesem Fall sogar Rasmus selbst einschließt. Ein großes Lob an Sebastián und alle anderen, die zu dieser Antwort beigetragen haben.
Nachteule
1
Danke Night Owl, aber ich bestehe darauf, dass dies nicht kugelsicher ist (wie die Antwort besagt, schlägt es fehl, wenn meine Funktion "inspect ()" mehr als einmal in einer einzelnen Zeile aufgerufen wird!). Ich würde das niemals in der Produktion verwenden. Es ist nur für eine Debugging-Inspektorfunktion gedacht, die niemals den Produktionsserver erreichen sollte.
Sebastián Grignoli
7

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 - Verwendung

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

quelle
4

Viele Antworten stellen die Nützlichkeit dieser Frage in Frage. Das Abrufen einer Referenz für eine Variable kann jedoch sehr nützlich sein. Besonders in Fällen mit Objekten und $ this . Meine Lösung funktioniert mit Objekten und auch als eigenschaftsdefinierte 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
K. Brunner
quelle
2

Angepasst an die obigen Antworten für viele Variablen, mit guter Leistung, nur ein $ GLOBALS-Scan für viele

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
        )

)
user1933288
quelle
1

Wenn die Variable austauschbar ist, müssen Sie irgendwo eine Logik haben , die bestimmt, welche Variable verwendet wird. Sie müssen lediglich den Variablennamen eingeben$variable diese 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, was Sie versuchen , tatsächlich zu tun könnte helfen, aber ich vermute , du bist Art und Weise, Art und Weise dieses Grübeln.

ceejayoz
quelle
1

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 möchte eine Funktion wie erwähnt haben).

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 versucht

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

Aber das scheitert auch ... :(

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

Ich möchte also eine Funktion, die den ORIGINAL-Namen einer Variablen erhält, wie er an eine Funktion übergeben wurde. Innerhalb der Funktion kann ich das auf keinen Fall wissen, wie es scheint. Das Übergeben von get_defined_vars () als Referenz im zweiten Beispiel oben hat mir etwas geholfen (Dank an Jean-Jacques Guegan für diese Idee). Die letztere Funktion begann zu funktionieren, gab aber immer noch nur die lokale Variable zurück ('Variable', nicht 'Farbe').

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

Aron Cederholm
quelle
1
Das grundlegende Problem besteht darin, dass Sie Werte an Funktionen übergeben, nicht an Variablen . Variablen sind temporär und spezifisch für ihren Umfang. Oft ist der Variablenname nicht der Schlüssel, unter dem Sie den Wert zwischenspeichern möchten, und häufig stellen Sie ihn ohnehin in einer Variablen mit einem anderen Namen wieder her (wie in Ihrem Beispiel). Wenn Sie wirklich zu faul sind, um den Namen des Schlüssels zu wiederholen, um sich die Variable zu merken, verwenden Sie cacheVariable(compact('color')).
Täuschung
1

Ich habe das:

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

Ich würde das vorziehen:

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

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

Das ist mein Anwendungsfall und ja, es hat mit Debugging zu tun. Ich stimme denen zu, die seine Verwendung anders in Frage stellen.

Will Fastie
quelle
1

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')
);
Dakiquang
quelle
0

Warum bauen Sie nicht einfach eine einfache Funktion und sagen 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' );
Ein alter Mann
quelle
0

Ich habe danach gesucht, aber nur beschlossen, den Namen weiterzugeben. Normalerweise habe ich den Namen sowieso in der Zwischenablage.

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

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

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

$FooBar = "a string";

$newArray = compact('FooBar');

Dies würde ein assoziatives Array mit dem Variablennamen als Schlüssel erstellen. Sie können dann das Array mit dem Schlüsselnamen durchlaufen, in dem Sie es benötigt haben.

foreach($newarray as $key => $value) {
    echo $key;
}
Budove
quelle
2
Cool, aber Sie müssen den Namen der Variablen kennen, um sie verwenden zu können. OP versucht, den Variablennamen programmgesteuert zu bestimmen.
Ein Kodierer
0

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

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

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

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

Janaka R Rajapaksha
quelle
Viel langsamer als die üblichen Methoden zum Deklarieren von Variablen.
David Spector
0

Ich weiß, dass dies alt ist und bereits beantwortet wurde, aber ich habe tatsächlich danach gesucht. Ich poste diese Antwort, um den Leuten ein wenig Zeit zu sparen und einige der Antworten zu verfeinern.

Option 1:

$data = array('$FooBar');  

$vars = [];  
$vars = preg_replace('/^\\$/', '', $data); 

$varname = key(compact($vars));  
echo $varname;

Drucke:

FooBar

Aus welchem ​​Grund auch immer Sie sich in einer solchen Situation befinden würden, es funktioniert tatsächlich.

.
Option 2:

$FooBar = "a string";  

$varname = trim(array_search($FooBar, $GLOBALS), " \t.");  
echo $varname;

Wenn $FooBarein eindeutiger Wert vorhanden ist, wird "FooBar" gedruckt. Wenn$FooBar leer oder null, wird der Name der ersten gefundenen leeren oder null-Zeichenfolge ausgegeben.

Es könnte als solches verwendet werden:

if (isset($FooBar) && !is_null($FooBar) && !empty($FooBar)) {
    $FooBar = "a string";
    $varname = trim(array_search($FooBar, $GLOBALS), " \t.");
}
Verblüfft
quelle
0

So habe ich es gemacht

function getVar(&$var) {
    $tmp = $var; // store the variable value
    $var = '_$_%&33xc$%^*7_r4'; // give the variable a new unique value
    $name = array_search($var, $GLOBALS); // search $GLOBALS for that unique value and return the key(variable)
    $var = $tmp; // restore the variable old value
    return $name;
}

Verwendung

$city  = "San Francisco";
echo getVar($city); // city

Hinweis: einige Versionen PHP 7 nicht richtig auf einen Fehler aufgrund arbeiten array_searchmit$GLOBALS , aber alle anderen Versionen funktionieren.

Siehe diese https://3v4l.org/UMW7V

Regen
quelle
-1

Verwenden Sie diese Option, um Benutzervariablen von global zu trennen und die Variable im Moment zu überprüfen.

function get_user_var_defined () 
{
    return array_slice($GLOBALS,8,count($GLOBALS)-8);     
}

function get_var_name ($var) 
{
    $vuser = get_user_var_defined(); 
    foreach($vuser as $key=>$value) 
    {
        if($var===$value) return $key ; 
    }
}
user1446000
quelle
@IMSoP Gemessen an der Ausgabe print implode( ' ', array_keys( $GLOBALS ));sieht es nach einer falschen Annahme über die Anzahl der "Standard" -Globals aus. Auf meinem System gibt es sieben Superglobale: $ _GET, $ _POST, $ _COOKIE, $ _FILES, $ _ENV, $ _REQUEST, $ _SERVER. Und es gibt auch Argv und Argc. Der Offset sollte also 9 sein. Es macht keinen Sinn, den dritten Parameter (Länge) anzugeben, da die Standardeinstellung ohnehin nur das Ende des Arrays ist.
Jeff
-2

Es kann als schnell und schmutzig angesehen werden, aber meine persönliche Präferenz ist es, eine Funktion / Methode wie diese zu verwenden:

public function getVarName($var) {      
  $tmp = array($var => '');
  $keys = array_keys($tmp);
  return trim($keys[0]);
}

Im Grunde wird nur ein assoziatives Array erstellt, das ein null / leeres Element enthält, wobei die Variable, für die Sie den Namen möchten, als Schlüssel verwendet wird.

Wir erhalten dann den Wert dieses Schlüssels mit array_keys und geben ihn zurück.

Offensichtlich wird dies schnell chaotisch und wäre in einer Produktionsumgebung nicht wünschenswert, aber es funktioniert für das vorgestellte Problem.

user3344253
quelle
1
Das ist der Wert der Variablen, nicht der Name der Variablen. Wie an anderer Stelle erwähnt, ist der Name nicht über Funktionsgrenzen hinweg portierbar.
Owen Beresford
3
minus eins, weil diese Funktion buchstäblich nichts anderes tut, als die Trimmung zurückzugeben ($ var);
Alexar
-3

Warum wir Globals verwenden müssen, um den Variablennamen zu erhalten ... können wir einfach wie unten verwenden.

    $variableName = "ajaxmint";

    echo getVarName('$variableName');

    function getVarName($name) {
        return str_replace('$','',$name);
    }
Ajaxmint
quelle
6
Weil das OP den Variablennamen nicht kennt. Wenn er das tun würde, würde er keine getVarName()Funktion brauchen . ;-)
FtDRbwLXw6
1
Dies gibt den Namen einer Variablen nicht als Zeichenfolge zurück, da '$variableName'es sich bereits um eine Zeichenfolge und nicht um eine Variable handelt. Wenn Sie diesen Trick mit können getVarName($variableName);, erhalten Sie eine positive Bewertung :)
Daniel W.
-4

Ich sehe den Anwendungsfall wirklich nicht ... Wenn Sie print_var_name ($ foobar) eingeben, was ist dann so schwierig (und anders) daran, stattdessen print ("foobar") einzugeben?

Denn selbst wenn Sie dies in einer Funktion verwenden würden, würden Sie den lokalen Namen der Variablen erhalten ...

In jedem Fall finden Sie hier das Reflexionshandbuch für den Fall, dass Sie etwas benötigen.

Vinko Vrsalovic
quelle
Print ("foobar") verarbeitet keine anderen Variablen.
Gary Willoughby
7
Anwendungsfall: Der Code enthält nur wenige Debugpunkte, die den gleichen Wert zurückgeben. Woher weißt du, welches zuerst ausgeführt wurde? Das Drucken eines Etiketts ist dann sehr nützlich.
Takeshin
Dann haben Sie nicht genug programmiert. Die meisten Sprachen, auf die ich gestoßen bin, haben eine Möglichkeit, dies zu tun, normalerweise einfach.
b01
@ b01 Ich habe viel getan. Ich bin mir vollkommen bewusst, dass es viele Sprachen gibt, die dies zulassen, aber das allein bedeutet nicht viel. Viele Sprachen bieten eine Möglichkeit, einfach zu arbeiten, und das bedeutet nicht, dass Sie sie verwenden sollten, um das Schreiben einer ordnungsgemäßen Flusskontrolle zu vermeiden. Dies ist aus meiner Sicht ein ähnlicher Fall. Ich bezweifle nicht, dass es berechtigte Fälle gibt, und deshalb habe ich mich über geeignete Anwendungsfälle dafür gewundert.
Vinko Vrsalovic