Jak uzyskać nazwę zmiennej jako ciąg znaków w PHP?


201

Powiedz, że mam ten kod PHP:

$FooBar = "a string";

potrzebuję takiej funkcji:

print_var_name($FooBar);

który drukuje:

FooBar

Wszelkie pomysły, jak to osiągnąć? Czy jest to w ogóle możliwe w PHP?


9
Jeśli potrzebujesz tego do czegoś innego niż debugowanie, robisz coś bardzo złego. Jaki jest twój przypadek użycia?
troelskn

10
Dobre pytanie. Potrzebowałem tego samego do debugowania.
trwa

17
+1 - Potrzebowałem tego do automatycznego generowania odpowiedzi XML lub JSON z modelowego obiektu PHP. Konieczność zawinięcia obiektu do innej nazwanej rootName => modelObjecttablicy po prostu dodaje niepotrzebnej głębi do odpowiedzi. Szkoda, że ​​nie zostało to uwzględnione w możliwościach odzwierciedlania środowiska wykonawczego języka.
Anurag

4
Potrzebowałem tego również w funkcji logowania. Chciałem móc wykonać następujące czynności: log ($ didTheSystemBlowUp); Aby pojawić się w pliku dziennika, takim jak: $ didTheSystemBlowUp = „jeszcze nie, ale już wkrótce”;
SeanDowney

4
Może to również być przydatne podczas wywoływania var_dump (), więc gdy wywołujesz jednocześnie kilka zmiennych, nie masz ręcznie wypisywanej nazwy zmiennej, aby odróżnić wyjścia vardupms.
PHPst

Odpowiedzi:


37

Możesz użyć get_defined_vars (), aby znaleźć nazwę zmiennej, która ma taką samą wartość jak ta, dla której próbujesz znaleźć nazwę. Oczywiście nie zawsze będzie to działać, ponieważ różne zmienne często mają te same wartości, ale jest to jedyny sposób, w jaki mogę to zrobić.

Edycja: get_defined_vars () wydaje się nie działać poprawnie, zwraca „var”, ponieważ $ var jest używane w samej funkcji. $ GLOBALS wydaje się działać, więc zmieniłem to na to.

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

    return false;
}

Edycja: aby było jasne, nie ma dobrego sposobu na zrobienie tego w PHP, prawdopodobnie dlatego, że nie powinieneś tego robić. Prawdopodobnie są lepsze sposoby robienia tego, co próbujesz zrobić.


2
Ahh Byłem wolny ;-) Myślałem tak samo, ale zamiast tego użyłem $ GLOBALS. Tak więc porównanie tożsamości daje wartość true dla równych wartości skalarnych ($ a = 'foo'; $ b = 'foo'; assert ($ a === $ b);)?
Argelbargel

Właściwie teraz, kiedy przetestowałem mój kod, mój kod zawsze zwracał „var”, ponieważ jest używany w funkcji. Kiedy zamiast tego używam $ GLOBALS, zwraca ona z jakiegoś powodu poprawną nazwę zmiennej. Więc zmienię powyższy kod, aby używał $ GLOBALS.
Jeremy Ruten

Tak, zdałem sobie sprawę, ale get_defined_vars () wystarczyło ta.
Gary Willoughby,

2
Istnieje wiele przypadków, w których ten kod nie będzie działał zgodnie z oczekiwaniami.
troelskn

122
Ten kod jest NAPRAWDĘ niepoprawny. Sprawdzanie, czy zmienna jest taka sama jak zmienna wysłana przez VALUE, jest bardzo głupim pomysłem. Miriady zmiennych mają wartość NULL w dowolnym punkcie. Myriady są ustawione na 1. To jest po prostu szalone.
Alex Weinstein,

49

Nie mogłem wymyślić sposobu, aby zrobić to skutecznie, ale wpadłem na to. Działa, dla ograniczonych zastosowań poniżej.

wzruszać ramionami

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

Działa w oparciu o linię, która wywołała funkcję, w której znajduje przekazany argument. Przypuszczam, że można go rozszerzyć do pracy z wieloma argumentami, ale, jak powiedzieli inni, gdyby można lepiej wyjaśnić sytuację, inne rozwiązanie prawdopodobnie Pracuj lepiej.


2
Działa to, ale tylko wtedy, gdy funkcja varName jest zdefiniowana w tym samym pliku co znaleziona zmienna.
rubo77

1
Tutaj znajdziesz lepszą implementację, która działa na kilku obejmuje: stackoverflow.com/a/19788805/1069083
rubo77

31

Czy możesz rozważyć zmianę podejścia i użycie nazwy zmiennej?

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

wtedy możesz po prostu

print($var_name);

dostać

FooBar

Oto link do instrukcji PHP na temat zmiennych zmiennych


42
Pracowałem z systemem, który intensywnie wykorzystywał zmienne zmienne. Ostrzegam cię, robi się naprawdę śmierdzący naprawdę szybko!
Icode4food,

3
w większości przypadków użytkownik chce uzyskać nazwę i wartość var. pomyśl „function debugvar ($ varname)”, a on zamierza nazwać to „debugvar („ foo ”)”, więc debugowanie wyświetli „foo = 123”. ze zmienną zmienną dostaną „foo” jest niezdefiniowany.
gcb

po prostu spójrz na to, co faktycznie robisz. Właśnie w tym przykładzie faktycznie UTWÓRZ zmienną $FooBaro wartości a stringpo prostu przeczytaj instrukcję. To okropne imho. nigdy nie przypisujesz zmiennej $FooBarwartości, ale ona tam jest. OUCH
Toskan

20

Wydaje się, że nikt nie wymienił podstawowych powodów, dla których jest to a) trudne i b) nierozsądne:

  • „Zmienna” to tylko symbol wskazujący na coś innego. W PHP wewnętrznie wskazuje na coś, co nazywa się „zval”, które może faktycznie być używane dla wielu zmiennych jednocześnie, ponieważ mają one tę samą wartość (PHP implementuje coś, co nazywa się „kopiuj przy zapisie”, więc $foo = $barnie trzeba alokuj dodatkową pamięć od razu) lub ponieważ zostały one przypisane (lub przekazane do funkcji) przez odniesienie (np $foo =& $bar.). Więc zval nie ma nazwy.
  • Gdy przekazujesz parametr do funkcji, tworzysz nową zmienną (nawet jeśli jest to odwołanie). Możesz przekazać coś anonimowego, "hello"ale gdy znajdziesz się w swojej funkcji, jest to jakakolwiek zmienna, którą nazwiesz. Jest to dość fundamentalne dla oddzielenia kodu: jeśli funkcja oparła się na tym, co zmienne wykorzystywane nazywać, to byłoby bardziej jakgoto niż odpowiednio oddzielnej funkcji.
  • Zmienne globalne są ogólnie uważane za zły pomysł. Wiele przykładów zakłada, że ​​można znaleźć zmienną, którą chcesz „odzwierciedlić”$GLOBALS , ale będzie to prawdą tylko wtedy, gdy źle skonstruujesz swój kod, a zmienne nie będą miały zakresu do jakiejś funkcji lub obiektu.
  • Istnieją zmienne nazwy, aby pomóc programistom odczytać ich kod. Zmiana nazw zmiennych, aby lepiej pasowały do ​​ich celów, jest bardzo powszechną praktyką refaktoryzacji, a cała sprawa polega na tym, że nie robi to żadnej różnicy.

Rozumiem teraz potrzebę debugowania (chociaż niektóre z proponowanych zastosowań wykraczają daleko poza to), ale jako ogólne rozwiązanie nie jest tak pomocne, jak mogłoby się wydawać: jeśli funkcja debugowania mówi, że twoja zmienna nosi nazwę „$ file ”, wciąż może to być dowolna z kilkudziesięciu zmiennych„ $ file ”w twoim kodzie lub zmienna, którą nazwałeś„ $ filename ”, ale przekazujesz do funkcji, której parametr nazywa się„ $ file ”.

O wiele bardziej użyteczną informacją jest to, skąd w kodzie została wywołana funkcja debugowania. Ponieważ możesz szybko znaleźć to w swoim edytorze, możesz zobaczyć, którą zmienną wypisałeś dla siebie, a nawet przesłać do niej całe wyrażenia za jednym razem (np debug('$foo + $bar = ' . ($foo + $bar)).).

W tym celu możesz użyć tego fragmentu u góry funkcji debugowania:

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

Istnieje już kilka dobrych odpowiedzi. Jest to więc tylko pesymizm, nawet w obliczu rzeczywistości.
a20

@ a20 Wszystkie odpowiedzi mają poważne zastrzeżenia, kiedy można je wykorzystać i kiedy się złamią; żadna nie jest prostym wyszukiwaniem dowolnej zmiennej do jej nazwy, ponieważ w rzeczywistości jest to niemożliwe. Niektóre wykonują wiele funky refleksji w celu debugowania, co jest w porządku; jednak moim zdaniem lepiej jest po prostu wypisać numer linii i samemu wyszukać linię źródła lub użyć interaktywnego debuggera, takiego jak XDebug.
IMSoP

14

To jest dokładnie to, czego chcesz - jest to gotowa do użycia funkcja „kopiuj i upuszczaj”, która odzwierciedla nazwę danego var:

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

WYKORZYSTANIE: print_var_name ($ FooBar)

DRUKUJ: FooBar

WSKAZÓWKA Teraz możesz zmienić nazwę funkcji i będzie ona nadal działać, a także korzystać z funkcji kilka razy w jednym wierszu! Dzięki @Cliffordlife


3
Fajnie, dzięki za to. Zmodyfikowałem nieco linię $ pat w $pat = '#(.*)'.__FUNCTION__.' *?\( *?(.*) *?\)(.*)#i';ten sposób, nie obchodzi mnie, jak nazywa się ta funkcja debugowania, i otrzymuję dokładnie to, co jest przekazywane do funkcji, tj. $ Hello lub „hello” (upuściłem dopasowanie $ dla przekazanej zmiennej w, w tej samej linii)
Cliffordlife

1
Fantastyczny kawałek kodu! Dzięki! Wydaje się jednak, że nie działa we wszystkich przypadkach. Wynik testowania na moim Ubuntu 18.04 z php 7.2.19: Nie działa, gdy jest używany wiele razy w tym samym wierszu kodu, niezależnie od tego, czy jest używany w jednym czy w osobnych wyrażeniach, ponieważ wtedy zwraca nazwę ostatniej zmiennej linia. Jeśli jest używany w tym samym wyrażeniu, ale w osobnych wierszach, działa. Działa w różnych wyrażeniach na różnych liniach.
Matty,

1
także ta funkcja powinna znajdować się w jednym wierszu bez „var_dump” - z połączonym print_var_name, echo, var_dumpwyjściem wysyłania$variable); echo ' '; var_dump($variable
BG Bruno

13

Lucas na PHP.net zapewnił niezawodny sposób sprawdzenia, czy zmienna istnieje. W swoim przykładzie iteruje przez kopię globalnej tablicy zmiennych (lub tablicy o zasięgu) zmiennych, zmienia wartość na losowo wygenerowaną wartość i sprawdza wygenerowaną wartość w skopiowanej tablicy.

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

Więc spróbuj:

$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

Pamiętaj, aby sprawdzić jego post na PHP.net: http://php.net/manual/en/language.variables.php


Jak uzyskać aktualny zakres w postaci tablicowej?
Sebastián Grignoli

Miły! Dla mnie brakuje tylko break;gdy jest równy w foreach + Zrobiłem użyteczną podstawową strukturę, aby automatycznie uzyskać var_name, jeśli zdefiniowano ją w funkcji. Jeśli często variable_name( $variable, ( empty(__FUNCTION__) ? false : get_defined_vars() ) );
kopiujesz i wklejasz

Jest to prawdopodobnie najszybszy i najczystszy sposób wykonania zadania, debugowanie prawdopodobnie obejmuje problemy z wydajnością. Funkcja powinna powrócić bezpośrednio w pętli foreach zamiast po prostu przypisywać bez zakłóceń. Biorąc pod uwagę, że GLOBALS może być duży, co może stanowić znaczną poprawę wydajności.
Jan

13

Z przyczyn debugowania wykonałem funkcję inspekcji. To jest jak print_r () na sterydach, podobnie jak Krumo, ale trochę bardziej skuteczne na obiektach. Chciałem dodać wykrywanie nazw var i wymyśliłem to, zainspirowany postem Nicka Presty na tej stronie. Wykrywa każde wyrażenie przekazane jako argument, nie tylko nazwy zmiennych.

Jest to tylko funkcja opakowania, która wykrywa przekazane wyrażenie. Działa w większości przypadków. Nie zadziała, jeśli wywołasz funkcję więcej niż jeden raz w tym samym wierszu kodu.

Działa to dobrze: die ( inspect ($ this-> getUser () -> hasCredential („delete”)) );

inspect () to funkcja, która wykryje przekazane wyrażenie.

Otrzymujemy: $ 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);

}

Oto przykład funkcji inspektora (i mojej klasy dInspect) w akcji:

http://inspect.ip1.cc

Na tej stronie teksty są w języku hiszpańskim, ale kod jest zwięzły i bardzo łatwy do zrozumienia.


1
errrm, czy to nie zależy od tego, czy masz zainstalowany debuger NuSphare?
Mawg mówi o przywróceniu Moniki

Umieściłem tam uproszczoną wersję tego kodu. Zmodyfikowałem również tę odpowiedź. Powinien działać teraz na każdej implementacji PHP5.
Sebastián Grignoli

Dzięki takiej pomysłowości uśmiecham się za każdym razem, gdy widzę, jak ludzie mówią: „nie da się tego zrobić” lub „nie jest możliwe”, w tym nawet samego Rasmusa. Uznanie dla Sebastiana i każdego, kto mógł przyczynić się do tej odpowiedzi.
Night Owl

1
Dzięki Night Owl, ale nalegam, aby to nie było kuloodporne (jak mówi odpowiedź, nie powiedzie się, jeśli moja funkcja „inspect ()” zostanie wywołana więcej niż raz w jednym wierszu!). Nigdy nie użyłbym tego w produkcji. Dotyczy tylko funkcji inspektora debugowania, która nigdy nie powinna dotrzeć do serwera produkcyjnego.
Sebastián Grignoli

7

Z php.net

@Alexandre - krótkie rozwiązanie

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

@Lucas - wykorzystanie

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

4

Wiele odpowiedzi kwestionuje przydatność tego. Jednak uzyskanie odniesienia do zmiennej może być bardzo przydatne. Zwłaszcza w przypadku przedmiotów i $ this . Moje rozwiązanie działa z obiektami, a także jako obiekty zdefiniowane we właściwościach:

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

Przykład powyższego:

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

2

Na podstawie powyższych odpowiedzi dla wielu zmiennych, z dobrą wydajnością, tylko jeden skan $ GLOBALS dla wielu

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
        )

)

1

Jeśli zmienna jest wymienne, trzeba mieć logiki gdzieś , że jest rozstrzygający, która zmienna przyzwyczaja. Wszystko, co musisz zrobić, to wpisać nazwę zmiennej$variable tej logice, podczas gdy robisz wszystko inne.

Myślę, że trudno nam zrozumieć, do czego jest to potrzebne. Przykładowy kod lub wyjaśnienie tego, czego rzeczywiście próbuje zrobić może pomóc, ale podejrzewam, że jesteś drogą, sposobem overthinking to.


1

Mam do tego ważny przypadek użycia.

Mam funkcję cacheVariable ($ var) (ok, mam pamięć podręczną funkcji ($ key, $ value), ale chciałbym mieć funkcję, jak wspomniano).

Celem jest wykonanie:

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

...

// another session

...

$myColour = getCachedVariable('colour');

Próbowałem z

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
}

Próbowałem też z

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

Ale to też się nie udaje ... :(

Jasne, mógłbym nadal robić pamięć podręczną („kolor”, $ kolor), ale jestem leniwy, wiesz ...;)

Tak więc, czego chcę, to funkcja, która otrzymuje ORYGINALNĄ nazwę zmiennej, tak jak została przekazana do funkcji. Wewnątrz funkcji nie ma możliwości, żeby to wiedzieć, jak się wydaje. Przekazywanie get_defined_vars () przez odniesienie w drugim powyższym przykładzie pomogło mi (dzięki Jean-Jacquesowi Gueganowi za ten pomysł) nieco. Ta ostatnia funkcja zaczęła działać, ale nadal zwracała tylko zmienną lokalną („zmienna”, a nie „kolor”).

Nie próbowałem jeszcze używać get_func_args () i get_func_arg (), $ {} - kombinacje konstrukcji i key (), ale przypuszczam, że to też się nie powiedzie.


1
Podstawowym problemem jest przekazywanie wartości do funkcji, a nie zmiennych . Zmienne są tymczasowe i specyficzne dla ich zakresu. Często nazwa zmiennej może nie być kluczem, pod którym chcesz buforować wartość, i często i tak przywrócisz zmienną o innej nazwie (jak w twoim przykładzie). Jeśli naprawdę jesteś zbyt leniwy, aby powtórzyć nazwę klucza, aby zapamiętać zmienną, użyj cacheVariable(compact('color')).
deceze

1

Mam to:

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

Wolałbym to:

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

Istniejąca funkcja wyświetla żółte pole z czerwonym konturem i pokazuje każdą zmienną według nazwy i wartości. Rozwiązanie tablicowe działa, ale jest trochę skomplikowane w pisaniu, gdy jest potrzebne.

To mój przypadek użycia i tak, ma to związek z debugowaniem. Zgadzam się z tymi, którzy kwestionują jego użycie w inny sposób.


1

Oto moje rozwiązanie oparte na Jeremy Ruten

class DebugHelper {

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

Użyj tego

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

0

Dlaczego po prostu nie zbudujesz prostej funkcji i nie powiesz jej?

/**
 * 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

Szukałem tego, ale po prostu postanowiłem przekazać nazwę, zwykle i tak mam ją w schowku.

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

$fruit='apple';
VarTest($fruit,'fruit');

0

Aby to osiągnąć, możesz użyć compact ().

$FooBar = "a string";

$newArray = compact('FooBar');

Spowoduje to utworzenie tablicy asocjacyjnej z nazwą zmiennej jako kluczem. Następnie możesz zapętlić tablicę, używając nazwy klucza tam, gdzie jest to potrzebne.

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

2
Fajnie, ale musisz znać nazwę zmiennej, aby jej użyć. OP chce programowo określić nazwę zmiennej.
koder

0

Myślę, że chcesz znać nazwę zmiennej z jej wartością. Aby to osiągnąć, możesz użyć tablicy asocjacyjnej.

użyj nazw zmiennych dla kluczy tablicy:

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

Gdy chcesz uzyskać nazwy zmiennych, użyj array_keys($vars), zwróci tablicę tych nazw zmiennych, które były używane w $varstablicy jako klucze.


Znacznie wolniej niż zwykłe metody deklarowania zmiennych.
David Spector,

0

Wiem, że to jest stare i już odpowiedziałem, ale tak naprawdę tego szukałem. Publikuję tę odpowiedź, aby zaoszczędzić trochę czasu na dopracowaniu niektórych odpowiedzi.

Opcja 1:

$data = array('$FooBar');  

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

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

Wydruki:

FooBar

Z jakiegokolwiek powodu znajdziesz się w takiej sytuacji, to faktycznie działa.

.
Opcja 2:

$FooBar = "a string";  

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

Jeśli $FooBarma unikalną wartość, wypisze „FooBar”. Jeśli$FooBar jest pusty lub zerowy, wypisze nazwę pierwszego znalezionego pustego lub zerowego ciągu.

Może być używany jako taki:

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

0

Tak to zrobiłem

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

Stosowanie

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

Uwaga: niektóre wersje PHP 7 nie będzie działać prawidłowo z powodu błędu w array_searchze $GLOBALSjednak wszystkie inne wersje będą działać.

Zobacz https://3v4l.org/UMW7V


-1

Użyj tego, aby odłączyć zmienne użytkownika od globalnego i sprawdzić zmienną w danym momencie.

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

@IMSoP Sądząc po wynikach print implode( ' ', array_keys( $GLOBALS ));, wygląda to na błędne założenie o liczbie „domyślnych” globali. W moim systemie jest siedem superglobali: $ _GET, $ _POST, $ _COOKIE, $ _FILES, $ _ENV, $ _REQUEST, $ _SERVER. Są też argumenty argv i argc. Zatem przesunięcie powinno wynosić 9. I nie ma sensu określać trzeciego parametru (długości), ponieważ domyślnie i tak biegnie on do końca tablicy.
Jeff

-2

Może to być uważane za szybkie i brudne, ale moje osobiste preferencje to używanie funkcji / metody takiej jak ta:

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

po prostu tworzy tablicę asocjacyjną zawierającą jeden pusty element, wykorzystując jako klucz zmienną, dla której chcesz nazwać.

następnie otrzymujemy wartość tego klucza za pomocą array_keys i zwracamy go.

oczywiście robi się to szybko bałagan i nie byłoby pożądane w środowisku produkcyjnym, ale działa na przedstawiony problem.


1
To jest wartość zmiennej, a nie nazwa zmiennej. Jak wskazano w innym miejscu, nazwa nie jest przenośna poza granicami funkcji.
Owen Beresford

3
minus jeden, ponieważ ta funkcja dosłownie nie robi nic, tylko zwraca przycinanie ($ var);
Alexar

-3

dlaczego musimy używać globałów, aby uzyskać nazwę zmiennej ... możemy użyć po prostu jak poniżej.

    $variableName = "ajaxmint";

    echo getVarName('$variableName');

    function getVarName($name) {
        return str_replace('$','',$name);
    }

6
Ponieważ OP nie zna nazwy zmiennej. Gdyby to zrobił, nie potrzebowałby getVarName()funkcji. ;-)
FtDRbwLXw6

1
To nie zwraca nazwy zmiennej jako ciągu, ponieważ '$variableName'jest już ciągiem, a nie zmienną. Jeśli potrafisz zrobić tę sztuczkę getVarName($variableName);, zyskujesz przychylność :)
Daniel W.

-4

Naprawdę nie widzę przypadku użycia ... Jeśli wpiszesz print_var_name ($ foobar), co jest tak trudne (i inne) w pisaniu print („foobar”) zamiast tego?

Ponieważ nawet gdybyś używał tego w funkcji, uzyskałbyś lokalną nazwę zmiennej ...

Tak czy inaczej, oto instrukcja refleksji na wypadek, gdybyś czegoś potrzebował.


Drukuj („foobar”) nie będzie obsługiwać innych zmiennych.
Gary Willoughby,

7
Przypadek użycia: masz kilka punktów debugowania w kodzie zwracających zrzut tej samej wartości. Skąd wiesz, który został najpierw wykonany? Drukowanie etykiety jest wtedy bardzo przydatne.
bierze

Więc nie zrobiłeś wystarczająco dużo programowania. Większość języków, z którymi się spotkałem, ma na to jakiś sposób, zwykle prosty.
b01

@ b01 Zrobiłem dużo. Wiem doskonale, że istnieje wiele języków, które na to pozwalają, ale to samo w sobie niewiele znaczy. Wiele języków oferuje sposób łatwego wykonywania goto, co nie oznacza, że ​​powinieneś go używać, aby uniknąć pisania odpowiedniej kontroli przepływu. Jest to moim zdaniem podobny przypadek. Nie wątpię, że istnieją uzasadnione przypadki i dlatego zastanawiałem się nad odpowiednimi przypadkami użycia.
Vinko Vrsalovic
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.