У меня есть функция
function my_dump($a,$name){ echo '<pre>'.$name.":\n"; var_export($a); echo '</pre>'; }
Как я могу достичь этого только одним аргументом, чтобы функция распознавала имя вызываемой переменной?
например:
my_dump($cool_variable_name);
выведет:
Имя: "cool_variable_name"
Содержимое: массив (…
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)
Если вам нужно отлаживать код, то использование таких инструментов, как 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), вам понадобится несколько более сложный парсер для извлечения имени переменной из вашего кода.
… Я прошу прощения за новый ответ вместо смены предыдущего, но было слишком долго (и, следовательно, неудобно) читать.
Ниже приведена функция из предыдущего ответа, которая улучшена для многократного использования этой функции. Эта версия способна получить имя правильной переменной в случае многократного использования в одной строке.
Он не способен получить имя более чем одной переменной – по крайней мере, потому что я не думаю, что это было бы хорошо (полезно для чего угодно).
Отличия:
новая обработка результата регулярного выражения
Параметр $ 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>[az]{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']; } } } }
Надеюсь, это поможет вам, как или лучше, чем предыдущая версия.
Изменить: новое выражение позволяет использовать больше типов переменных (не только обычных).
Если это простой скрипт, где все переменные определены в глобальной области, вы можете получить решение $ 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);
Это невозможно.
Когда функция вызывается, значение параметра вставляется в ваш $ a, поэтому каждая попытка получить его имя возвращает «a».
http://us3.php.net/get_defined_vars не будет работать, потому что он возвращает только переменные внутри вашей функции (это означает «a»).
Вы можете использовать массив с одним элементом, но я думаю, это не то, что вы намереваетесь сделать.