3

我有一个功能

function my_dump($a,$name){
    echo '<pre>'.$name.":\n";
    var_export($a);
    echo '</pre>';
}

如何仅使用一个参数来实现这一点,以便函数识别被调用变量本身的名称?

例如:

my_dump($cool_variable_name);

将输出:

名称:“cool_variable_name”
内容:数组(...

4

5 回答 5

10

如果你需要调试代码,那么使用像 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 示例),您将需要一个稍微复杂的解析器来从代码中提取变量名称。

于 2013-11-05T12:17:21.927 回答
1

...请您原谅新答案而不是更改以前的答案,但是阅读时间太长(因此不舒服)。

以下是先前答案中的功能,该功能已针对此功能的多次使用进行了改进。此版本能够在一行中多次使用的情况下获取正确变量的名称。

它不能获得多个变量的名称 - 至少因为我认为它不会很好(对任何事情都有用)。

差异:

  • 添加整数参数 $Index
  • 正则表达式的新函数
  • 新的正则表达式
  • 正则表达式结果的新处理

  • 参数 $Index 不是必需的 - 但是除了第一次使用该函数之外,它会忽略它会给出错误的结果

  • 表达式中的 \x20 表示空格

  • 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'];
                }
            }
        }
    }
    

我希望它会帮助你,喜欢或比以前的版本更好。

编辑:新表达式允许使用更多类型的变量(不仅常见)。

于 2014-02-04T23:35:27.523 回答
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)
于 2014-02-02T22:20:27.010 回答
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);
于 2013-11-05T12:16:47.363 回答
-1

没有办法做到这一点。

当函数被调用时,参数的值被粘贴到你的 $a 中,所以每次尝试获取它的名称都会返回“a”。

http://us3.php.net/get_defined_vars将失败,因为它只返回函数内部的变量(这意味着“a”)。

您可以将数组与一个项目一起使用,但我想这不是您打算做的。

于 2013-11-05T10:35:02.707 回答