说我有这个PHP代码:
$FooBar = "a string";
然后我需要一个这样的函数:
print_var_name($FooBar);
打印:
FooBar
任何想法如何实现这一目标?这在PHP中甚至可能吗?
我想不出有效地做到这一点的方法,但我想出了这个.它适用于下面的有限用途.
耸
// Returns Array ( [0] => $foo [1] => foo ) Array ( [0] => $bar [1] => bar ) Array ( [0] => $baz [1] => baz )
它基于调用函数的行来工作,在那里它找到你传入的参数.我想它可以扩展为使用多个参数,但是,正如其他人所说,如果你能更好地解释这种情况,另一种解决方案可能工作得更好.
您可以使用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中没有好办法,这可能是因为你不应该这样做.做你正在做的事情可能有更好的方法.
您可以考虑更改方法并使用变量名称吗?
$var_name = "FooBar"; $$var_name = "a string";
那么你可以
print($var_name);
要得到
FooBar
这是关于变量变量的PHP手册的链接
似乎没有人提到为什么这是a)困难和b)不明智的根本原因:
"变量"只是指向别的东西的符号.在PHP中,它内部指向称为"zval"的东西,它实际上可以同时用于多个变量,因为它们具有相同的值(PHP实现了一种称为"copy-on-write"的东西,所以$foo = $bar
不需要直接分配额外的内存)或因为它们已被引用(例如$foo =& $bar
)分配(或传递给函数).所以zval没有名字.
将参数传递给函数时,您正在创建一个新变量(即使它是一个引用).你可以传递一些匿名的东西,比如"hello"
,但是一旦进入你的函数,它就是你命名的变量.这是相当基本的代码分离:如果一个函数在什么变量依赖使用被称为,这将是更像是一个goto
比一个适当的独立机构.
全局变量通常被认为是一个坏主意.这里有很多例子假设您想要"反映"的变量可以在其中找到$GLOBALS
,但只有在您的代码结构严重且变量没有作用于某个函数或对象的情况下才会出现这种情况.
变量名称可以帮助程序员读取他们的代码.重命名变量以更好地适应其目的是一种非常常见的重构实践,并且重点是它没有任何区别.
现在,我明白了这个愿望,调试(虽然有些建议的用法远不止于此),但作为一个通用的解决方案它实际上不是像你想的一样有用:如果你的调试功能,说你的变量称为"$文件",这可能仍然是代码中的几十个"$ 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帖子的启发.它会检测作为参数传递的任何表达式,而不仅仅是变量名称.
这只是检测传递表达式的包装函数.适用于大多数情况.如果在同一行代码中多次调用该函数,它将无法工作.
这工作正常:死(检查($这个 - >的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); }
以下是检查器函数(和我的dInspect类)的实例:
http://inspect.ip1.cc
文本在该页面中是西班牙语,但代码简洁且易于理解.
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; }
然后尝试:
$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上查看他的帖子:http://php.net/manual/en/language.variables.php
这正是你想要的 - 它是一个随时可用的"复制和放入"函数,它回显给定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); }
用法:print_var_name($ FooBar)
打印:FooBar
提示 现在您可以重命名该功能,它仍然可以工作,并且可以在一行中多次使用该功能!感谢@Cliffordlife
来自php.net
@Alexandre - 简短的解决方案
@Lucas - 用法
my_object_property = "My object property string."; } } $obj = new myclass; echo vname($obj->my_object_property, $obj); // Outputs: my_object_property ?>