如何在函数内找到变量的名称?

时间:2013-11-05 10:10:14

标签: php

我有一个功能

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

如何只使用一个参数实现此功能,以便函数识别被调用变量本身的名称?

例如:

my_dump($cool_variable_name);

将输出:

  

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

5 个答案:

答案 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
  • 正则表达式的新功能
  • 新正则表达式
  • 正则表达式结果的新处理

  • 参数$ 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”)。

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