如何在PHP中获得一个string的variables名?

说我有这个PHP代码:

$FooBar = "a string"; 

然后我需要一个这样的function:

 print_var_name($FooBar); 

打印:

 FooBar 

任何想法如何实现这一目标? 这甚至可能在PHP?

你可以使用get_defined_vars()来find一个variables的名字,这个variables的名字和你试图find这个名字的variables的名字相同。 显然这不会总是有效,因为不同的variables通常具有相同的值,但是这是我唯一能想到的方法。

编辑:get_defined_vars()似乎没有正常工作,它返回“var”,因为$ var在函数本身中使用。 $全球似乎工作,所以我已经改变了。

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

编辑:要清楚,没有好办法在PHP中这样做,这可能是因为你不应该这样做。 有可能更好的方式做你想做的事情。

我想不出有效地做到这一点的方法,但我想出了这个。 它适用于下面的有限使用。

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

它的工作原理是基于调用函数的那一行,在那里它find了你传入的参数。我想这个函数可以扩展到多个参数一起工作,但是和其他人一样,如果你能更好地解释这个情况,另一个解决scheme可能会工作得更好。

你可能会考虑改变你的方法,并使用一个variables名称?

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

那么你可以

 print($var_name); 

要得到

 FooBar 

这里是关于variablesvariables的PHP手册的链接

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

  • “variables”只是一个指向别的东西的符号。 在PHP中,它内部指向一个名为“zval”的东西,它可以同时用于多个variables,或者是因为它们具有相同的值(PHP实现了所谓的“copy-on-write”),所以$foo = $bar不需要马上分配额外的内存),或者因为它们已经被引用(例如$foo =& $bar )分配(或传递给一个函数)。 所以一个zval没有名字。
  • 当你传递一个参数给一个函数时,你正在创build一个新的variables(即使它是一个引用)。 你可以传递一些匿名的东西,比如"hello" ,但是一旦进入你的函数,它就是你指定的任何variables。 这对于代码分离来说是相当基础的:如果一个函数依赖于一个variables被调用,它将更像是一个goto不是一个正确分离的函数。
  • 全局variables通常被认为是一个坏主意。 这里的很多例子都假设你想要“反映”的variables可以在$GLOBALSfind,但是只有当你的代码构造的很糟糕,variables没有被作用于某个函数或者对象时,这才是真实的。
  • variables名称可以帮助程序员读取他们的代码。 重命名variables以更好地适合他们的目的是一个非常常见的重构实践,而且重要的是它没有任何区别。

现在,我理解debugging的愿望(尽pipe一些build议的用法远远超出了这个范围),但作为一个通用的解决scheme,它并不像你想象的那样有帮助:如果你的debugging函数说你的variables被称为“$ file “,这仍然可以是你的代码中的几十个”$ file“variables中的任何一个,或者是一个你称为”$ filename“但是传递给一个函数的参数被称为”$ file“的variables。

一个更有用的信息是你的代码中调用debugging函数的地方。 既然你可以在你的编辑器中快速find它,你可以看到你自己输出了哪个variables,甚至可以一次性传入整个expression式(例如debug('$foo + $bar = ' . ($foo + $bar)) )。

为此,您可以在debuggingfunction的顶部使用这段代码:

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

我为了debugging的原因做了一个检查function。 这就像print_r()类似于类固醇,很像Krumo,但对物体更有效一些。 我想添加var名称检测,并出现在这个页面上,由Nick Presta的post启发。 它检测作为parameter passing的任何expression式,而不仅仅是variables名称。

这只是检测传递的expression式的包装函数。 适用于大多数情况。 如果您在相同的代码行中多次调用该函数,它将不起作用。

这工作正常:死( 检查( $ this-> getUser() – > hasCredential(“删除”) );

inspect()是将检测传递的expression式的函数。

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

下面是检查器function(和我的dInspect类)的一个例子:

http://inspect.ip1.cc

文本在西class牙文页面,但代码简洁,真正容易理解。

PHP.net上的Lucas提供了一个可靠的方法来检查variables是否存在。 在他的例子中,他遍历全局variables数组(或范围数组)的variables副本,将值更改为随机生成的值,并检查复制数组中的生成值。

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

然后尝试:

 $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 

请务必在PHP.net上检查他的post: http : //php.net/manual/en/language.variables.php

许多回复质疑这个的有用性。 但是,获取variables的引用可能非常有用。 特别是在对象和$ this的情况下。 我的解决scheme与对象一起工作,并作为属性定义的对象:

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

上面的例子:

 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 

从php.net

@Alexandre – 简短的解决scheme

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

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

这正是你想要的 – 准备好使用“copy and drop in”函数来回显给定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)

打印:FooBar

提示这不是防弹的:如果函数被多次调用(在一行中),它​​将会失败!

如果variables是可互换的,那么必须有逻辑确定哪个variables被使用。 所有你需要做的就是把variables名放在$variable logic $variable中,而你正在做其他的事情。

我想我们都很难理解你需要什么。 示例代码或者你实际上想要什么的解释可能会有所帮助,但是我怀疑你是这样做的。

我其实有一个有效的用例。

我有一个函数cacheVariable($ var)(好吧,我有一个函数caching($键,$值),但我想有一个函数提到)。

目的是做:

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

 // another session 

 $myColour = getCachedVariable('colour'); 

我曾尝试过

 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 } 

我也试过了

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

但是这也失败了…… 🙁

当然,我可以继续做caching('颜色',$颜色),但我很懒,你知道…;)

所以,我想要的是一个函数,获取variables的原始名称,因为它被传递给一个函数。 在函数内部,我无法知道这一点。 在上面的第二个例子中通过引用传递get_defined_vars()有助于我(感谢Jean-Jacques Guegan的这个想法)。 后者函数开始工作,但它仍然只是保持返回局部variables('variables',而不是'颜色')。

我还没有尝试过使用get_func_args()和get_func_arg(),$ {} – constructs和key(),但是我认为它也会失败。

我有这个:

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

我宁愿这样做:

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

现有function显示一个带红色轮廓的黄色框,并按名称和值显示每个variables。 arrays解决scheme工作,但有点复杂,需要时键入。

这是我的用例,是的,它确实与debugging有关。 我同意那些质疑其使用的人。

从上面的答案适应许多variables,具有良好的性能,只是一个$ 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 ) ) 

你为什么不build立一个简单的function,并告诉它?

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

这是基于Jeremy Ruten解决scheme

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

使用它

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

此时使用此从全局分离用户variables来检查variables。

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

我正在寻找这个,但只是决定通过名称,反正我通常在剪贴板的名称。

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

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

使用数组键的variables名称:

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

当你想得到variables名时,使用array_keys($vars) ,它将返回一个在$vars数组中使用的variables名的数组,因为它是键。

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

为什么我们必须使用全局variables来获取variables名…我们可以像下面那样使用。

  $variableName = "ajaxmint"; echo getVarName('$variableName'); function getVarName($name) { return str_replace('$','',$name); } 

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

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

基本上它只是创build一个包含一个null / empty元素的关联数组,使用您想要的名称作为variables的关键字。

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

显然这会变得凌乱并且在生产环境中不可取,但是对于所提出的问题是有效的。

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

 $FooBar = "a string"; $newArray = compact('FooBar'); 

这将创build一个variables名为关键字的关联数组。 然后,您可以在需要的地方使用密钥名称遍历数组。

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

我真的没有看到用例…如果你要inputprint_var_name($ foobar),那么inputprint(“foobar”)又有什么困难(和不同)呢?

因为即使你在一个函数中使用它,你也会得到variables的本地名称。

无论如何,这里是reflection手册 ,以防在那里有你需要的东西。