如何在PHP中将变量名作为字符串获取?

时间:2021-10-31 23:38:49

Say i have this PHP code:

假设我有这个PHP代码:

$FooBar = "a string";

i then need a function like this:

然后我需要一个这样的函数:

print_var_name($FooBar);

which prints:

打印:

FooBar

Any Ideas how to achieve this? Is this even possible in PHP?

有什么想法可以实现吗?这在PHP中是可能的吗?

22 个解决方案

#1


33  

You could use get_defined_vars() to find the name of a variable that has the same value as the one you're trying to find the name of. Obviously this will not always work, since different variables often have the same values, but it's the only way I can think of to do this.

您可以使用get_defined_vars()查找一个变量的名称,该变量的值与要查找的变量的名称相同。显然,这并不总是有效,因为不同的变量通常具有相同的值,但这是我能想到的唯一方法。

Edit: get_defined_vars() doesn't seem to be working correctly, it returns 'var' because $var is used in the function itself. $GLOBALS seems to work so I've changed it to that.

编辑:get_defined_vars()似乎不能正常工作,它返回'var',因为在函数本身中使用了$var。$GLOBALS似乎有用,所以我把它改成了这个。

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

    return false;
}

Edit: to be clear, there is no good way to do this in PHP, which is probably because you shouldn't have to do it. There are probably better ways of doing what you're trying to do.

编辑:明确地说,在PHP中没有很好的方法来实现这一点,这可能是因为您不需要这么做。也许有更好的方法去做你想做的事。

#2


39  

I couldn't think of a way to do this efficiently either but I came up with this. It works, for the limited uses below.

我也想不出一种有效的方法但是我想到了这个。它适用于以下有限的用途。

shrug

耸耸肩

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

It works based on the line that called the function, where it finds the argument you passed in. I suppose it could be expanded to work with multiple arguments but, like others have said, if you could explain the situation better, another solution would probably work better.

它基于调用函数的行来工作,在这行中它会找到您传入的参数。我认为它可以扩展为使用多个参数,但是,正如其他人所说,如果你能更好地解释情况,另一个解决方案可能会更好。

#3


23  

You might consider changing your approach and using a variable variable name?

您可以考虑更改方法并使用变量名吗?

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

then you could just

然后你可以

print($var_name);

to get

得到

FooBar

Here's the link to the PHP manual on Variable variables

下面是有关变量的PHP手册的链接

#4


17  

No-one seems to have mentioned the fundamental reasons why this is a) hard and b) unwise:

似乎没有人提到过这是一种艰难和愚蠢的根本原因:

  • A "variable" is just a symbol pointing at something else. In PHP, it internally points to something called a "zval", which can actually be used for multiple variables simultaneously, either because they have the same value (PHP implements something called "copy-on-write" so that $foo = $bar doesn't need to allocate extra memory straight away) or because they have been assigned (or passed to a function) by reference (e.g. $foo =& $bar). So a zval has no name.
  • “变量”只是指向其他东西的符号。在PHP中,它在内部指向一个叫做“zval”,同时可以用于多个变量,要么因为他们有相同的值(PHP实现所谓的“即写即拷”这$ foo = $酒吧马上不需要分配额外的内存)或因为他们被分配(或传递给一个函数)通过引用(例如$ foo = & $酒吧)。所以zval没有名字。
  • When you pass a parameter to a function you are creating a new variable (even if it's a reference). You could pass something anonymous, like "hello", but once inside your function, it's whatever variable you name it as. This is fairly fundamental to code separation: if a function relied on what a variable used to be called, it would be more like a goto than a properly separate function.
  • 当您将一个参数传递给一个函数时,您正在创建一个新的变量(即使它是一个引用)。你可以传递一些匿名的东西,比如“hello”,但是一旦进入你的函数,它就是你命名它为的任何变量。这对于代码分离是相当重要的:如果一个函数依赖于一个变量过去的调用,那么它更像是一个goto,而不是一个完全独立的函数。
  • Global variables are generally considered a bad idea. A lot of the examples here assume that the variable you want to "reflect" can be found in $GLOBALS, but this will only be true if you've structured your code badly and variables aren't scoped to some function or object.
  • 全局变量通常被认为是一个坏主意。这里的许多示例假设您想要“反射”的变量可以在$GLOBALS中找到,但这只有在您对代码进行了糟糕的结构化并且变量不受某个函数或对象的作用域限制的情况下才会成立。
  • Variable names are there to help programmers read their code. Renaming variables to better suit their purpose is a very common refactoring practice, and the whole point is that it doesn't make any difference.
  • 变量名可以帮助程序员阅读他们的代码。重命名变量以更好地适应它们的目的是一种非常常见的重构实践,其要点在于它不会产生任何影响。

Now, I understand the desire for this for debugging (although some of the proposed usages go far beyond that), but as a generalised solution it's not actually as helpful as you might think: if your debug function says your variable is called "$file", that could still be any one of dozens of "$file" variables in your code, or a variable which you have called "$filename" but are passing to a function whose parameter is called "$file".

现在,我理解的欲望,这对于调试(尽管一些建议的应用远不止),但是作为一个普遍的解决方案实际上不是一样帮助你可能会想:如果你的调试功能说变量叫做“美元文件”,仍然可以任何一个几十个“$文件”变量在代码中,或一个变量,称为“文件名”美元但传递一个函数的参数是被称为“文件”美元。

A far more useful piece of information is where in your code the debug function was called from. Since you can quickly find this in your editor, you can see which variable you were outputting for yourself, and can even pass whole expressions into it in one go (e.g. debug('$foo + $bar = ' . ($foo + $bar))).

一个更有用的信息是在代码中调用debug函数的位置。因为您可以在编辑器中快速找到它,所以您可以看到自己输出的是哪个变量,甚至可以一次将整个表达式传递给它(例如debug('$foo + $bar = ')。美元($ foo + bar)))。

For that, you can use this snippet at the top of your debug function:

为此,您可以在调试函数的顶部使用这个代码片段:

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

#5


12  

I made an inspection function for debugging reasons. It's like print_r() on steroids, much like Krumo but a little more effective on objects. I wanted to add the var name detection and came out with this, inspired by Nick Presta's post on this page. It detects any expression passed as an argument, not only variable names.

由于调试原因,我做了一个检查函数。它就像类固醇上的print_r(),很像Krumo,但对对象更有效。我想添加var name detection,并根据Nick Presta在这个页面上的帖子得出这个结果。它检测作为参数传递的任何表达式,而不仅仅是变量名。

This is only the wrapper function that detects the passed expression. Works on most of the cases. It will not work if you call the function more than once in the same line of code.

这只是检测传递的表达式的包装器函数。适用于大多数情况。如果在同一行代码中多次调用该函数,那么它将无法工作。

This works fine: die(inspect($this->getUser()->hasCredential("delete")));

这没问题:死(检查($ This - > getUser()- > hasCredential(“删除”)));

inspect() is the function that will detect the passed expression.

inspect()是用来检测已传递表达式的函数。

We get: $this->getUser()->hasCredential("delete")

我们得到:$ this - > getUser()- > hasCredential(“删除”)

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

}

Here's an example of the inspector function (and my dInspect class) in action:

下面是inspector函数(以及我的dInspect类)的一个实例:

http://inspect.ip1.cc

http://inspect.ip1.cc

Texts are in spanish in that page, but code is concise and really easy to understand.

这一页的文本是西班牙语,但是代码是简洁的,而且非常容易理解。

#6


9  

Lucas on PHP.net provided a reliable way to check if a variable exists. In his example, he iterates through a copy of the global variable array (or a scoped array) of variables, changes the value to a randomly generated value, and checks for the generated value in the copied array.

PHP.net上的Lucas提供了一种检查变量是否存在的可靠方法。在他的示例中,他遍历变量的全局变量数组(或作用域数组)的副本,将值更改为随机生成的值,并检查复制数组中生成的值。

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

Then try:

然后尝试:

$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

Be sure to check his post on PHP.net: http://php.net/manual/en/language.variables.php

一定要检查他在PHP.net上的帖子:http://php.net/manual/en/language.variables.php。

#7


4  

From php.net

从php.net

@Alexandre - short solution

@Alexandre——短期解决方案

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

@Lucas - usage

@Lucas——使用

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

#8


4  

Many replies question the usefulness of this. However, getting a reference for a variable can be very useful. Especially in cases with objects and $this. My solution works with objects, and as property defined objects as well:

许多回答质疑这种做法的有效性。然而,获取变量的引用是非常有用的。特别是在对象和$this的情况下。我的解决方案适用于对象,也适用于属性定义的对象:

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

Example for the above:

上面的例子:

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

#9


3  

This is exactly what you want - its a ready to use "copy and drop in" function that echo the name of a given var:

这正是您想要的——它可以使用“复制和删除”函数来响应给定var的名称:

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

USAGE: print_var_name($FooBar)

用法:print_var_name($ FooBar)

PRINT: FooBar

打印:FooBar

HINT This is not bullet proof: if function is called more than once (in a single line) it will fail!

提示这不是子项目证明:如果函数被调用多次(在一行中),它将失败!

#10


2  

Adapted from answers above for many variables, with good performance, just one $GLOBALS scan for many

从上面的答案为许多变量,具有良好的性能,只需一个$GLOBALS扫描为许多

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
        )

)

#11


1  

If the variable is interchangable, you must have logic somewhere that's determining which variable gets used. All you need to do is put the variable name in $variable within that logic while you're doing everything else.

如果变量是可交换的,那么您必须在确定使用哪个变量的某个地方有逻辑。您所需要做的就是在该逻辑中将变量名放入$variable中,而您正在执行其他操作。

I think we're all having a hard time understanding what you're needing this for. Sample code or an explanation of what you're actually trying to do might help, but I suspect you're way, way overthinking this.

我想我们都很难理解你为什么需要这个。示例代码或对您实际要做的事情的解释可能会有所帮助,但我怀疑您想得太多了。

#12


1  

I actually have a valid use case for this.

我有一个有效的用例。

I have a function cacheVariable($var) (ok, I have a function cache($key, $value), but I'd like to have a function as mentioned).

我有一个函数cacheVariable($var)(好的,我有一个函数缓存($key, $value),但是我希望有一个前面提到的函数)。

The purpose is to do:

目的是:

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

...

// another session

...

$myColour = getCachedVariable('colour');

I have tried with

我已经尝试

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
}

I have also tried with

我也试过了。

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

But this fails as well... :(

但这也失败了……:(

Sure, I could continue to do cache('colour', $colour), but I'm lazy, you know... ;)

当然,我可以继续做缓存(' color ' $colour),但我很懒,你知道……,)

So, what I want is a function that gets the ORIGINAL name of a variable, as it was passed to a function. Inside the function there is no way I'm able to know that, as it seems. Passing get_defined_vars() by reference in the second example above helped me (Thanks to Jean-Jacques Guegan for that idea) somewhat. The latter function started working, but it still only kept returning the local variable ('variable', not 'colour').

我想要的是一个函数,当它被传递给一个函数时,它会得到一个变量的原始名称。在函数内部,我不可能知道,就像它看起来的那样。在上面的第二个示例中通过引用传递get_defined_vars(),这在某种程度上对我有所帮助(感谢Jean-Jacques Guegan的想法)。后一个函数开始工作,但它仍然只返回局部变量('variable',而不是' color ')。

I haven't tried yet to use get_func_args() and get_func_arg(), ${}-constructs and key() combined, but I presume it will fail as well.

我还没有尝试将get_func_args()和get_func_arg()、${}-construct和key()组合使用,但我认为它也会失败。

#13


1  

I have this:

我有这个:

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

I would prefer this:

我宁愿这个:

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

The existing function displays a yellow box with a red outline and shows each variable by name and value. The array solution works but is a little convoluted to type when it is needed.

现有函数显示一个带有红色轮廓的黄色框,并通过名称和值显示每个变量。数组解决方案可以工作,但是在需要的时候输入有点麻烦。

That's my use case and yes, it does have to do with debugging. I agree with those who question its use otherwise.

这是我的用例,是的,它确实与调试有关。我同意那些质疑它的用途的人。

#14


0  

Why don't you just build a simple function and TELL it?

为什么不构建一个简单的函数并告诉它呢?

/**
 * 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' );

#15


0  

Here's my solution based on Jeremy Ruten

这是我基于Jeremy Ruten的解决方案。

class DebugHelper {

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

using it

使用它

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

#16


0  

I was looking for this but just decided to pass the name in, I usually have the name in the clipboard anyway.

我一直在找这个,但是我决定把名字传进去,我通常都会把名字写在剪贴板上。

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

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

#17


0  

I think you want to know variable name with it's value. You can use an associative array to achieve this.

我想你想知道变量名和它的值。您可以使用关联数组来实现这一点。

use variable names for array keys:

对数组键使用变量名:

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

When you want to get variable names, use array_keys($vars), it will return an array of those variable names that used in your $vars array as it's keys.

当您想获得变量名时,使用array_keys($vars),它将返回一个变量名数组,这些变量名在$vars数组中用作键。

I use this way to get column names of the table in my Database class.

我使用这种方法获取数据库类中的表的列名。

#18


-1  

why we have to use globals to get variable name... we can use simply like below.

为什么我们必须使用全局变量名…我们可以像下面这样简单地使用。

    $variableName = "ajaxmint";

    echo getVarName('$variableName');

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

#19


-1  

Use this to detach user variables from global to check variable at the moment.

使用此方法将用户变量从全局变量分离到当前的变量。

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

#20


-1  

It may be considered quick and dirty, but my own personal preference is to use a function/method like this:

它可能被认为是快速和肮脏的,但是我个人的偏好是使用这样的函数/方法:

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

basically it just creates an associative array containing one null/empty element, using as a key the variable for which you want the name.

基本上,它只是创建一个包含一个空/空元素的关联数组,使用要名称的变量作为键。

we then get the value of that key using array_keys and return it.

然后我们使用array_keys获取该键的值并返回它。

obviously this gets messy quick and wouldn't be desirable in a production environment, but it works for the problem presented.

显然,这很快就会变得混乱,在生产环境中是不可取的,但它适用于所提出的问题。

#21


-1  

You could use compact() to achieve this.

您可以使用compact()来实现这一点。

$FooBar = "a string";

$newArray = compact('FooBar');

This would create an associative array with the variable name as the key. You could then loop through the array using the key name where you needed it.

这将创建一个以变量名作为键的关联数组。然后可以在需要的地方使用键名对数组进行循环。

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

#22


-3  

I really fail to see the use case... If you will type print_var_name($foobar) what's so hard (and different) about typing print("foobar") instead?

我真的看不到用例……如果您要输入print_var_name($foobar),那么输入print(“foobar”)有什么困难(和不同)呢?

Because even if you were to use this in a function, you'd get the local name of the variable...

因为即使你在函数中使用这个,你也会得到变量的本地名…

In any case, here's the reflection manual in case there's something you need in there.

在任何情况下,这是反射手册,以防您需要一些东西。

#1


33  

You could use get_defined_vars() to find the name of a variable that has the same value as the one you're trying to find the name of. Obviously this will not always work, since different variables often have the same values, but it's the only way I can think of to do this.

您可以使用get_defined_vars()查找一个变量的名称,该变量的值与要查找的变量的名称相同。显然,这并不总是有效,因为不同的变量通常具有相同的值,但这是我能想到的唯一方法。

Edit: get_defined_vars() doesn't seem to be working correctly, it returns 'var' because $var is used in the function itself. $GLOBALS seems to work so I've changed it to that.

编辑:get_defined_vars()似乎不能正常工作,它返回'var',因为在函数本身中使用了$var。$GLOBALS似乎有用,所以我把它改成了这个。

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

    return false;
}

Edit: to be clear, there is no good way to do this in PHP, which is probably because you shouldn't have to do it. There are probably better ways of doing what you're trying to do.

编辑:明确地说,在PHP中没有很好的方法来实现这一点,这可能是因为您不需要这么做。也许有更好的方法去做你想做的事。

#2


39  

I couldn't think of a way to do this efficiently either but I came up with this. It works, for the limited uses below.

我也想不出一种有效的方法但是我想到了这个。它适用于以下有限的用途。

shrug

耸耸肩

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

It works based on the line that called the function, where it finds the argument you passed in. I suppose it could be expanded to work with multiple arguments but, like others have said, if you could explain the situation better, another solution would probably work better.

它基于调用函数的行来工作,在这行中它会找到您传入的参数。我认为它可以扩展为使用多个参数,但是,正如其他人所说,如果你能更好地解释情况,另一个解决方案可能会更好。

#3


23  

You might consider changing your approach and using a variable variable name?

您可以考虑更改方法并使用变量名吗?

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

then you could just

然后你可以

print($var_name);

to get

得到

FooBar

Here's the link to the PHP manual on Variable variables

下面是有关变量的PHP手册的链接

#4


17  

No-one seems to have mentioned the fundamental reasons why this is a) hard and b) unwise:

似乎没有人提到过这是一种艰难和愚蠢的根本原因:

  • A "variable" is just a symbol pointing at something else. In PHP, it internally points to something called a "zval", which can actually be used for multiple variables simultaneously, either because they have the same value (PHP implements something called "copy-on-write" so that $foo = $bar doesn't need to allocate extra memory straight away) or because they have been assigned (or passed to a function) by reference (e.g. $foo =& $bar). So a zval has no name.
  • “变量”只是指向其他东西的符号。在PHP中,它在内部指向一个叫做“zval”,同时可以用于多个变量,要么因为他们有相同的值(PHP实现所谓的“即写即拷”这$ foo = $酒吧马上不需要分配额外的内存)或因为他们被分配(或传递给一个函数)通过引用(例如$ foo = & $酒吧)。所以zval没有名字。
  • When you pass a parameter to a function you are creating a new variable (even if it's a reference). You could pass something anonymous, like "hello", but once inside your function, it's whatever variable you name it as. This is fairly fundamental to code separation: if a function relied on what a variable used to be called, it would be more like a goto than a properly separate function.
  • 当您将一个参数传递给一个函数时,您正在创建一个新的变量(即使它是一个引用)。你可以传递一些匿名的东西,比如“hello”,但是一旦进入你的函数,它就是你命名它为的任何变量。这对于代码分离是相当重要的:如果一个函数依赖于一个变量过去的调用,那么它更像是一个goto,而不是一个完全独立的函数。
  • Global variables are generally considered a bad idea. A lot of the examples here assume that the variable you want to "reflect" can be found in $GLOBALS, but this will only be true if you've structured your code badly and variables aren't scoped to some function or object.
  • 全局变量通常被认为是一个坏主意。这里的许多示例假设您想要“反射”的变量可以在$GLOBALS中找到,但这只有在您对代码进行了糟糕的结构化并且变量不受某个函数或对象的作用域限制的情况下才会成立。
  • Variable names are there to help programmers read their code. Renaming variables to better suit their purpose is a very common refactoring practice, and the whole point is that it doesn't make any difference.
  • 变量名可以帮助程序员阅读他们的代码。重命名变量以更好地适应它们的目的是一种非常常见的重构实践,其要点在于它不会产生任何影响。

Now, I understand the desire for this for debugging (although some of the proposed usages go far beyond that), but as a generalised solution it's not actually as helpful as you might think: if your debug function says your variable is called "$file", that could still be any one of dozens of "$file" variables in your code, or a variable which you have called "$filename" but are passing to a function whose parameter is called "$file".

现在,我理解的欲望,这对于调试(尽管一些建议的应用远不止),但是作为一个普遍的解决方案实际上不是一样帮助你可能会想:如果你的调试功能说变量叫做“美元文件”,仍然可以任何一个几十个“$文件”变量在代码中,或一个变量,称为“文件名”美元但传递一个函数的参数是被称为“文件”美元。

A far more useful piece of information is where in your code the debug function was called from. Since you can quickly find this in your editor, you can see which variable you were outputting for yourself, and can even pass whole expressions into it in one go (e.g. debug('$foo + $bar = ' . ($foo + $bar))).

一个更有用的信息是在代码中调用debug函数的位置。因为您可以在编辑器中快速找到它,所以您可以看到自己输出的是哪个变量,甚至可以一次将整个表达式传递给它(例如debug('$foo + $bar = ')。美元($ foo + bar)))。

For that, you can use this snippet at the top of your debug function:

为此,您可以在调试函数的顶部使用这个代码片段:

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

#5


12  

I made an inspection function for debugging reasons. It's like print_r() on steroids, much like Krumo but a little more effective on objects. I wanted to add the var name detection and came out with this, inspired by Nick Presta's post on this page. It detects any expression passed as an argument, not only variable names.

由于调试原因,我做了一个检查函数。它就像类固醇上的print_r(),很像Krumo,但对对象更有效。我想添加var name detection,并根据Nick Presta在这个页面上的帖子得出这个结果。它检测作为参数传递的任何表达式,而不仅仅是变量名。

This is only the wrapper function that detects the passed expression. Works on most of the cases. It will not work if you call the function more than once in the same line of code.

这只是检测传递的表达式的包装器函数。适用于大多数情况。如果在同一行代码中多次调用该函数,那么它将无法工作。

This works fine: die(inspect($this->getUser()->hasCredential("delete")));

这没问题:死(检查($ This - > getUser()- > hasCredential(“删除”)));

inspect() is the function that will detect the passed expression.

inspect()是用来检测已传递表达式的函数。

We get: $this->getUser()->hasCredential("delete")

我们得到:$ this - > getUser()- > hasCredential(“删除”)

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

}

Here's an example of the inspector function (and my dInspect class) in action:

下面是inspector函数(以及我的dInspect类)的一个实例:

http://inspect.ip1.cc

http://inspect.ip1.cc

Texts are in spanish in that page, but code is concise and really easy to understand.

这一页的文本是西班牙语,但是代码是简洁的,而且非常容易理解。

#6


9  

Lucas on PHP.net provided a reliable way to check if a variable exists. In his example, he iterates through a copy of the global variable array (or a scoped array) of variables, changes the value to a randomly generated value, and checks for the generated value in the copied array.

PHP.net上的Lucas提供了一种检查变量是否存在的可靠方法。在他的示例中,他遍历变量的全局变量数组(或作用域数组)的副本,将值更改为随机生成的值,并检查复制数组中生成的值。

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

Then try:

然后尝试:

$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

Be sure to check his post on PHP.net: http://php.net/manual/en/language.variables.php

一定要检查他在PHP.net上的帖子:http://php.net/manual/en/language.variables.php。

#7


4  

From php.net

从php.net

@Alexandre - short solution

@Alexandre——短期解决方案

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

@Lucas - usage

@Lucas——使用

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

#8


4  

Many replies question the usefulness of this. However, getting a reference for a variable can be very useful. Especially in cases with objects and $this. My solution works with objects, and as property defined objects as well:

许多回答质疑这种做法的有效性。然而,获取变量的引用是非常有用的。特别是在对象和$this的情况下。我的解决方案适用于对象,也适用于属性定义的对象:

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

Example for the above:

上面的例子:

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

#9


3  

This is exactly what you want - its a ready to use "copy and drop in" function that echo the name of a given var:

这正是您想要的——它可以使用“复制和删除”函数来响应给定var的名称:

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

USAGE: print_var_name($FooBar)

用法:print_var_name($ FooBar)

PRINT: FooBar

打印:FooBar

HINT This is not bullet proof: if function is called more than once (in a single line) it will fail!

提示这不是子项目证明:如果函数被调用多次(在一行中),它将失败!

#10


2  

Adapted from answers above for many variables, with good performance, just one $GLOBALS scan for many

从上面的答案为许多变量,具有良好的性能,只需一个$GLOBALS扫描为许多

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
        )

)

#11


1  

If the variable is interchangable, you must have logic somewhere that's determining which variable gets used. All you need to do is put the variable name in $variable within that logic while you're doing everything else.

如果变量是可交换的,那么您必须在确定使用哪个变量的某个地方有逻辑。您所需要做的就是在该逻辑中将变量名放入$variable中,而您正在执行其他操作。

I think we're all having a hard time understanding what you're needing this for. Sample code or an explanation of what you're actually trying to do might help, but I suspect you're way, way overthinking this.

我想我们都很难理解你为什么需要这个。示例代码或对您实际要做的事情的解释可能会有所帮助,但我怀疑您想得太多了。

#12


1  

I actually have a valid use case for this.

我有一个有效的用例。

I have a function cacheVariable($var) (ok, I have a function cache($key, $value), but I'd like to have a function as mentioned).

我有一个函数cacheVariable($var)(好的,我有一个函数缓存($key, $value),但是我希望有一个前面提到的函数)。

The purpose is to do:

目的是:

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

...

// another session

...

$myColour = getCachedVariable('colour');

I have tried with

我已经尝试

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
}

I have also tried with

我也试过了。

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

But this fails as well... :(

但这也失败了……:(

Sure, I could continue to do cache('colour', $colour), but I'm lazy, you know... ;)

当然,我可以继续做缓存(' color ' $colour),但我很懒,你知道……,)

So, what I want is a function that gets the ORIGINAL name of a variable, as it was passed to a function. Inside the function there is no way I'm able to know that, as it seems. Passing get_defined_vars() by reference in the second example above helped me (Thanks to Jean-Jacques Guegan for that idea) somewhat. The latter function started working, but it still only kept returning the local variable ('variable', not 'colour').

我想要的是一个函数,当它被传递给一个函数时,它会得到一个变量的原始名称。在函数内部,我不可能知道,就像它看起来的那样。在上面的第二个示例中通过引用传递get_defined_vars(),这在某种程度上对我有所帮助(感谢Jean-Jacques Guegan的想法)。后一个函数开始工作,但它仍然只返回局部变量('variable',而不是' color ')。

I haven't tried yet to use get_func_args() and get_func_arg(), ${}-constructs and key() combined, but I presume it will fail as well.

我还没有尝试将get_func_args()和get_func_arg()、${}-construct和key()组合使用,但我认为它也会失败。

#13


1  

I have this:

我有这个:

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

I would prefer this:

我宁愿这个:

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

The existing function displays a yellow box with a red outline and shows each variable by name and value. The array solution works but is a little convoluted to type when it is needed.

现有函数显示一个带有红色轮廓的黄色框,并通过名称和值显示每个变量。数组解决方案可以工作,但是在需要的时候输入有点麻烦。

That's my use case and yes, it does have to do with debugging. I agree with those who question its use otherwise.

这是我的用例,是的,它确实与调试有关。我同意那些质疑它的用途的人。

#14


0  

Why don't you just build a simple function and TELL it?

为什么不构建一个简单的函数并告诉它呢?

/**
 * 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' );

#15


0  

Here's my solution based on Jeremy Ruten

这是我基于Jeremy Ruten的解决方案。

class DebugHelper {

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

using it

使用它

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

#16


0  

I was looking for this but just decided to pass the name in, I usually have the name in the clipboard anyway.

我一直在找这个,但是我决定把名字传进去,我通常都会把名字写在剪贴板上。

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

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

#17


0  

I think you want to know variable name with it's value. You can use an associative array to achieve this.

我想你想知道变量名和它的值。您可以使用关联数组来实现这一点。

use variable names for array keys:

对数组键使用变量名:

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

When you want to get variable names, use array_keys($vars), it will return an array of those variable names that used in your $vars array as it's keys.

当您想获得变量名时,使用array_keys($vars),它将返回一个变量名数组,这些变量名在$vars数组中用作键。

I use this way to get column names of the table in my Database class.

我使用这种方法获取数据库类中的表的列名。

#18


-1  

why we have to use globals to get variable name... we can use simply like below.

为什么我们必须使用全局变量名…我们可以像下面这样简单地使用。

    $variableName = "ajaxmint";

    echo getVarName('$variableName');

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

#19


-1  

Use this to detach user variables from global to check variable at the moment.

使用此方法将用户变量从全局变量分离到当前的变量。

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

#20


-1  

It may be considered quick and dirty, but my own personal preference is to use a function/method like this:

它可能被认为是快速和肮脏的,但是我个人的偏好是使用这样的函数/方法:

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

basically it just creates an associative array containing one null/empty element, using as a key the variable for which you want the name.

基本上,它只是创建一个包含一个空/空元素的关联数组,使用要名称的变量作为键。

we then get the value of that key using array_keys and return it.

然后我们使用array_keys获取该键的值并返回它。

obviously this gets messy quick and wouldn't be desirable in a production environment, but it works for the problem presented.

显然,这很快就会变得混乱,在生产环境中是不可取的,但它适用于所提出的问题。

#21


-1  

You could use compact() to achieve this.

您可以使用compact()来实现这一点。

$FooBar = "a string";

$newArray = compact('FooBar');

This would create an associative array with the variable name as the key. You could then loop through the array using the key name where you needed it.

这将创建一个以变量名作为键的关联数组。然后可以在需要的地方使用键名对数组进行循环。

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

#22


-3  

I really fail to see the use case... If you will type print_var_name($foobar) what's so hard (and different) about typing print("foobar") instead?

我真的看不到用例……如果您要输入print_var_name($foobar),那么输入print(“foobar”)有什么困难(和不同)呢?

Because even if you were to use this in a function, you'd get the local name of the variable...

因为即使你在函数中使用这个,你也会得到变量的本地名…

In any case, here's the reflection manual in case there's something you need in there.

在任何情况下,这是反射手册,以防您需要一些东西。