说我有这个PHP代码:
$FooBar = "a string";
然后,我需要一个这样的功能:
print_var_name($FooBar);
打印:
FooBar
任何想法如何实现这一目标?在PHP中甚至可能吗?
rootName => modelObject
数组中只会给响应增加不必要的深度。希望这已融入到语言的运行时反映功能中。
说我有这个PHP代码:
$FooBar = "a string";
然后,我需要一个这样的功能:
print_var_name($FooBar);
打印:
FooBar
任何想法如何实现这一目标?在PHP中甚至可能吗?
rootName => modelObject
数组中只会给响应增加不必要的深度。希望这已融入到语言的运行时反映功能中。
Answers:
您可以使用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中没有好的方法可以做到这一点,这可能是因为您不必这样做。可能有更好的方法来做您想做的事情。
我也没有办法有效地做到这一点,但我想到了这一点。适用于以下有限用途。
耸耸肩
<?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
)
它基于调用该函数的行,在该行中找到您传入的参数。我想可以将其扩展为与多个参数一起使用,但是,就像其他人所说的那样,如果您可以更好地解释这种情况,则可能会有另一种解决方案工作更好。
您可能会考虑更改方法并使用变量变量名?
$var_name = "FooBar";
$$var_name = "a string";
那你就可以
print($var_name);
要得到
FooBar
$FooBar
带有该值的变量,a string
只需阅读手册即可。这是可怕的恕我直言。您永远不会为变量分配$FooBar
值,但是它在那里。OUCH
没有人似乎已经提到的根本原因,为什么这是一个)硬盘和b)不明智的:
$foo = $bar
不需要立即分配额外的内存),或者因为它们已通过引用分配(或传递给函数)(例如$foo =& $bar
)。因此,zval没有名称。"hello"
但是一旦进入函数,就可以将其命名为任何变量。这对于代码分离来说是相当基础的:如果一个函数依赖于曾经调用过的变量,那么它将goto
比一个正确分离的函数更像是一个。$GLOBALS
,但是只有当您对代码的结构不良并且变量的作用域不限于某些函数或对象时,这才是正确的。现在,我了解了调试的愿望(尽管一些建议的用法远不止于此),但是作为一种通用解决方案,它实际上并没有您想象的那么有用:如果您的调试函数说您的变量称为“ $ 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'];
这正是您想要的-它是现成的可使用“复制和插入”功能,可呼应给定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
$pat = '#(.*)'.__FUNCTION__.' *?\( *?(.*) *?\)(.*)#i';
这种方式稍稍修改了$ pat行,我不在乎此调试函数的名称,我确切地知道了传递给函数的内容,即$ hello或“ hello”(我为传递的变量删除了$ match在同一行)
print_var_name, echo, var_dump
发送输出$variable); echo ' '; var_dump($variable
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
break;
在foreach中发现相等时+如果在函数中定义了我,我也做了可用的基本结构来自动获取var_name。如果您经常复制粘贴或有更好的主意来改进它,请使用variable_name( $variable, ( empty(__FUNCTION__) ? false : get_defined_vars() ) );
由于调试原因,我做了一个检查功能。就像类固醇上的print_r()一样,就像Krumo一样,但对对象更有效。我想添加var名称检测功能,并在此页面上受尼克·普雷斯塔(Nick Presta)的启发而提出。它检测任何作为参数传递的表达式,而不仅仅是变量名。
这只是包装器函数检测传递的表达式。适用于大多数情况。如果您在同一行代码中多次调用该函数,它将无法正常工作。
正常工作:死(检查($ this-> getUser()-> hasCredential(“ delete”)));
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类)的示例:
该页面中的文本为西班牙语,但是代码简洁明了,非常容易理解。
来自php.net
@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-用法
<?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
?>
许多答复对此表示怀疑。但是,获取变量的引用可能非常有用。特别是在有对象和$ 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}";
}
以上示例:
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
根据上面的答案改编为许多变量,并具有良好的性能,只需对多个变量进行一次$ 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
)
)
我实际上有一个有效的用例。
我有一个函数cacheVariable($ var)(好吧,我有一个函数cache($ key,$ value),但是我想有一个提到的函数)。
目的是:
$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));
}
但这也失败了... :(
当然,我可以继续进行缓存('colour',$ colour),但是我很懒,你知道...;)
因此,我想要的是一个函数,该函数获取传递给函数的变量的原始名称。在函数内部,似乎无法知道。在上面的第二个示例中,通过引用传递get_defined_vars()对我有所帮助(感谢Jean-Jacques Guegan的想法)。后一个函数开始工作,但是它仍然只返回局部变量(“变量”,而不是“颜色”)。
我还没有尝试过将get_func_args()和get_func_arg(),$ {}-constructs和key()结合使用,但是我想它也会失败。
cacheVariable(compact('color'))
。
这是我基于的解决方案 Jeremy Ruten
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')
);
您为什么不构建一个简单的函数并告诉它呢?
/**
* 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' );
我一直在寻找这个,但只是决定将名称传递进去,无论如何我通常在剪贴板中都有这个名称。
function VarTest($my_var,$my_var_name){
echo '$'.$my_var_name.': '.$my_var.'<br />';
}
$fruit='apple';
VarTest($fruit,'fruit');
我想您想知道变量名称及其值。您可以使用关联数组来实现此目的。
对数组键使用变量名:
$vars = array('FooBar' => 'a string');
当您想要获取变量名时,请使用array_keys($vars)
,它将返回一个在$vars
数组中用作键的变量名数组。
我知道这很旧并且已经回答了,但是我实际上正在寻找这个。我发布此答案是为了节省人们一些时间来完善一些答案。
选项1:
$data = array('$FooBar');
$vars = [];
$vars = preg_replace('/^\\$/', '', $data);
$varname = key(compact($vars));
echo $varname;
印刷品:
FooBar
无论出于什么原因,您都会发现自己处于这种情况,它确实可以工作。
。
选项2:
$FooBar = "a string";
$varname = trim(array_search($FooBar, $GLOBALS), " \t.");
echo $varname;
如果$FooBar
拥有唯一值,它将打印“ FooBar”。如果$FooBar
为空或null,则将打印找到的第一个空或null字符串的名称。
它可以这样使用:
if (isset($FooBar) && !is_null($FooBar) && !empty($FooBar)) {
$FooBar = "a string";
$varname = trim(array_search($FooBar, $GLOBALS), " \t.");
}
这是我做的方式
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;
}
用法
$city = "San Francisco";
echo getVar($city); // city
注:一些PHP 7版本将无法正常因错误的工作array_search
有$GLOBALS
,但是所有其他版本将工作。
使用此命令可以将用户变量与全局变量分开,以检查当前变量。
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 ;
}
}
print implode( ' ', array_keys( $GLOBALS ));
似乎是对“默认”全局变量数量的错误假设。在我的系统上,有七个超全局变量:$ _GET,$ _ POST,$ _ COOKIE,$ _ FILES,$ _ ENV,$ _ REQUEST,$ _ SERVER。还有argv和argc。因此,偏移量应为9。并且指定第三个参数(长度)毫无意义,因为默认值始终会一直运行到数组的末尾。
它可能被认为是快速又肮脏的,但是我个人的喜好是使用这样的函数/方法:
public function getVarName($var) {
$tmp = array($var => '');
$keys = array_keys($tmp);
return trim($keys[0]);
}
基本上,它只是创建一个包含一个null / empty元素的关联数组,并将要使用其名称的变量用作键。
然后,我们使用array_keys获得该键的值并返回它。
显然,这很快就会变得杂乱无章,在生产环境中是不希望的,但是它可以解决所提出的问题。
为什么我们必须使用全局变量来获取变量名...我们可以像下面这样简单地使用。
$variableName = "ajaxmint";
echo getVarName('$variableName');
function getVarName($name) {
return str_replace('$','',$name);
}
getVarName()
功能。;-)
'$variableName'
已经是字符串,而不是变量。如果您可以使用做这把戏getVarName($variableName);
,您将获得投票:)
我真的看不到用例...如果您将输入print_var_name($ foobar),那么输入print(“ foobar”)有何困难(和不同之处)?
因为即使在函数中使用它,您也会获得变量的本地名称...
无论如何,这是反射手册,以防万一。