假设我有这样的PHP代码:

$FooBar = "a string";

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

print_var_name($FooBar);

打印:

FooBar

有什么想法如何实现这一点?这在PHP中可能吗?


当前回答

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

$FooBar = "a string";

$newArray = compact('FooBar');

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

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

其他回答

似乎没有人提到这是a)困难和b)不明智的根本原因:

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

现在,我理解这种调试的愿望(尽管一些建议的用法远远超出了这一点),但作为一种通用的解决方案,它实际上并没有你想象的那么有用:如果你的调试函数说你的变量是“$file”,那仍然可能是你代码中数十个“$file”变量中的任何一个,或者一个你称为“$filename”的变量,但传递给一个参数为“$file”的函数。

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

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

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

出于调试的原因,我做了一个检查函数。它就像print_r()的类固醇,很像Krumo,但对对象更有效一点。我想添加var名称检测,灵感来自于Nick Presta的帖子。它检测作为参数传递的任何表达式,而不仅仅是变量名。

这只是检测传递表达式的包装器函数。 大多数案子都没问题。 如果在同一行代码中多次调用该函数,则它将不起作用。

这很好: 死(检查($ this - > getUser()——> hasCredential(“删除”)));

Inspect()是检测传递表达式的函数。

我们得到:$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);

}

下面是inspector函数(和我的dInspect类)的一个例子:

http://inspect.ip1.cc

该页面的文本是西班牙语,但代码简洁,非常容易理解。

我也想不出有效的方法但我想到了这个。对于下面的有限用途,它是有效的。

耸耸肩

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

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

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

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

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

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

编辑: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;
}

编辑:需要明确的是,在PHP中没有好的方法来做到这一点,这可能是因为您不应该这样做。也许有更好的方法来做你想做的事情。