我有一个功能
function my_dump($a,$name){
echo '<pre>'.$name.":\n";
var_export($a);
echo '</pre>';
}
如何只使用一个参数实现此功能,以便函数识别被调用变量本身的名称?
例如:
my_dump($cool_variable_name);
将输出:
名称:“cool_variable_name”
内容:数组(...
答案 0 :(得分:7)
如果需要调试代码,那么使用像xdebug这样的工具比自制的变量转储更加灵活和高效;但是debug_backtrace()(虽然开销很大)可能会给你你需要的东西。提取调试转储函数调用的文件名和行号,并解析该行以提取调用函数时使用的变量名称
function my_dump($a) {
$backtrace = debug_backtrace()[0];
$fh = fopen($backtrace['file'], 'r');
$line = 0;
while (++$line <= $backtrace['line']) {
$code = fgets($fh);
}
fclose($fh);
preg_match('/' . __FUNCTION__ . '\s*\((.*)\)\s*;/u', $code, $name);
echo '<pre>'.trim($name[1]).":\n";
var_export($a);
echo '</pre>';
}
$foo = 'bar';
$baz = array(
'Hello',
'World'
);
my_dump($foo);
my_dump(
$baz
);
如果您的PHP版本不支持阵列解除引用,请更改
$backtrace = debug_backtrace()[0];
到
$backtrace = debug_backtrace();
$backtrace = $backtrace[0];
如果你对my_dump()的调用跨越多行(比如我的$ baz示例),你需要一个稍微复杂的解析器来从你的代码中提取变量名。
答案 1 :(得分:1)
function my_dump($a) {
$backtrace = debug_backtrace()[0];
$fh = fopen($backtrace['file'], 'r');
$line = 0;
while (++$line <= $backtrace['line']) {
$code = fgets($fh);
}
fclose($fh);
preg_match('/' . __FUNCTION__ . '\s*\((.*)\)\s*;/u', $code, $name);
echo '<pre>'.trim($name[1]).":\n";
var_export($a);
echo '</pre>';
}
它运行不正确 - 因为使用的表达式没有给出正确的结果。
使用\ s *没有意义,因为函数名和括号之间没有任何参数。
使用;在表达方面也没有意义。至少因为只允许单独使用此函数,其中此函数的结果被赋予else变量。但有时可能需要将此函数用作参数。
使用(。*)将允许作为参数给出的变量名后面的所有内容 - 即使有分号。
因此,需要从结果中排除末尾括号的符号。有很多方法可以做到这一点。
您可以使用下面的函数代码或此函数(或其他内容)
'/'.__FUNCTION__.'\((\w+)\)/'
整个函数可以非常简化(例如,这是类函数的情况):
protected function Get_VariableNameAsText($Variable="")
{
$File = file(debug_backtrace()[0]['file']);
for($Line = 1; $Line < count($File); $Line++)
{
if($Line == debug_backtrace()[0]['line']-1)
{
preg_match('/'.__FUNCTION__.'\(([^\)]*)\)/', $File[$Line], $VariableName);
return trim($VariableName[1]);
}
}
}
我删除了var_export的使用,因为我不知道为什么要使用它,当我只想将变量名称作为字符串(文本)。并且在此功能之外打印给定字符串会更好。
如果您没有5.4或更高版本,则需要更改代码
$File = file(debug_backtrace()[0]['file']);
if($Line == debug_backtrace()[0]['line']-1)
在
$Trace = debug_backtrace();
$File = file($Trace[0]['file']);
if($Line == $Trace[0]['line']-1)
答案 2 :(得分:1)
...请原谅新答案,而不是改变以前的答案,但阅读时间过长(因而不舒服)。
以下是上一个答案的功能,该功能针对此功能的多次使用进行了改进。如果在一行中多次使用,此版本能够获取正确变量的名称。
它无法获得多个变量的名称 - 至少因为我认为它不会很好(对任何事物都有用)。
的差异:
正则表达式结果的新处理
参数$ Index是不需要的 - 但是除了第一次使用该函数之外,它忽略其他任何东西都会产生错误的结果
\ x20 in expression表示空格
try-catch块中的异常类和异常消息可以根据需要重写
可以更改或删除功能的受保护状态
protected function Get_VariableNameAsText($Variable="", $Index="")
{
$File = file(debug_backtrace()[0]['file']);
try
{
if(!empty($Index) && !is_integer($Index))
{
throw new UniT_Exception(UniT_Exception::UNIT_EXCEPTIONS_MAIN_PARAM, UniT_Exception::UNIT_EXCEPTIONS_PARAM_VALTYPE);
}
}
catch(UniT_Exception $Exception)
{
$Exception -> ExceptionWarning(__CLASS__, __FUNCTION__, $this -> Get_Parameters(__CLASS__, __FUNCTION__)[1], gettype($Index), 'integer');
}
for($Line = 1; $Line < count($File); $Line++)
{
if($Line == debug_backtrace()[0]['line']-1)
{
preg_match_all('/'.__FUNCTION__.'\((?<type>[a-z]{1,}\:{2}\${1}|\$this\x20{0,1}\-\>{1}\x20{0,1}|\${1})(?<variable>[A-Za-z0-9_]{1,})\x20{0,1}\,{0,1}\x20{0,1}(?<index>[0-9]{0,})\x20{0,}\)/', $File[$Line], $VariableName, PREG_SET_ORDER);
if(empty($Index))
{
return $VariableName[0]['type'].$VariableName[0]['variable'];
}
else
{
return $VariableName[$Index]['type'].$VariableName[$Index]['variable'];
}
}
}
}
我希望它会比以前的版本更好或更好。
编辑:新表达式允许使用更多类型的变量(不仅是常见的)。
答案 3 :(得分:0)
如果它是一个简单的脚本,所有变量都在全局范围内定义,那么你可以获得$ GLOBALS解决方案:
function my_dump($a){
if(is_string($a) and isset($GLOBALS[$a])) {
echo "varname: $a\n";
$a=&$GLOBALS[$a];
}
echo '<pre>'.$name.":\n";
var_export($a);
echo '</pre>';
}
这样你就可以用变量名来调用转储函数
my_dump("cool_variable_name");
而不是
my_dump($cool_variable_name);
答案 4 :(得分:-1)
没有办法做到这一点。
当调用该函数时,参数的值被粘贴到$ a中,因此每次尝试获取它的名称都会返回“a”。
http://us3.php.net/get_defined_vars将失败,因为它只返回函数内的变量(即“a”)。
您可以使用包含一个项目的数组,但我想这不是您打算做的。