Как узнать имя переменной внутри функции?

У меня есть функция

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

Как я могу достичь этого только одним аргументом, чтобы функция распознавала имя вызываемой переменной?

например:

my_dump($cool_variable_name);

выведет:

Имя: "cool_variable_name"
Содержимое: array (...

Ответ 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

Если вам нужно отлаживать код, то использование таких инструментов, как xdebug, намного более гибко и эффективно, чем исходные дампы homebrew; но 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), вам понадобится немного более сложный парсер для извлечения имени переменной из вашего кода.

Ответ 3

... Я прошу прощения за новый ответ вместо смены предыдущего, но было бы слишком долго (и, следовательно, неудобно) читать.

Ниже приведена функция из предыдущего ответа, которая улучшена для многократного использования этой функции. Эта версия способна получить имя правильной переменной в случае многократного использования в одной строке.

Он не способен получить имя более чем одной переменной - по крайней мере, потому что я не думаю, что это было бы хорошо (полезно для чего угодно).

Отличия:

  • добавление целочисленного параметра $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'];
                }
            }
        }
    }
    

Я надеюсь, что это поможет вам, например, или лучше, чем предыдущая версия.

Изменить: Новое выражение позволяет использовать больше типов переменных (не только обычных).

Ответ 4

Если это простой script, где все переменные определены в глобальной области, вы можете получить решение $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);

Ответ 5

Нет никакого способа сделать это.

Когда функция вызывается, значение параметра вставляется в ваш $a, поэтому каждая попытка получить его имя возвращает "a".

http://us3.php.net/get_defined_vars будет терпеть неудачу, поскольку он возвращает только переменные внутри вашей функции (это означает "a" ).

Вы можете использовать массив с одним элементом, но я думаю, что не то, что вы намереваетесь сделать.