Я нахожу, что иногда debug_backtrace()
не включает номер строки для вызова. Есть ли какая-то причина, почему это так, и любой способ исправить это?
Заранее спасибо.
PS И да, вызовы, которые он опускает номера строк, это мой собственный код, а не внутренний PHP-код.
Рассмотрим следующий код:
<? class BtTest { public function getTheItem() { var_dump( debug_backtrace( false ) ); $bt = debug_backtrace( false ); return $bt[1]; } public function __call( $methodName, $methodArgs ) { return $this->getTheItem(); } } $o = new BtTest(); $bti = $o->test(); assert( 'array_key_exists("function", $bti)' ); assert( 'array_key_exists("line", $bti)' ); assert( 'array_key_exists("file", $bti)' );
Выполнение приведенного выше примера генерирует следующий результат:
array(3) { [0]=> array(6) { ["file"]=> string(53) "/somewhere/in/the/filesystem/tests/bt-test-so.php" ["line"]=> int(13) ["function"]=> string(10) "getTheItem" ["class"]=> string(6) "BtTest" ["type"]=> string(2) "->" ["args"]=> array(0) { } } [1]=> array(4) { ["function"]=> string(6) "__call" ["class"]=> string(6) "BtTest" ["type"]=> string(2) "->" ["args"]=> array(2) { [0]=> &string(4) "test" [1]=> &array(0) { } } } [2]=> array(6) { ["file"]=> string(53) "/somewhere/in/the/filesystem/tests/bt-test-so.php" ["line"]=> int(18) ["function"]=> string(4) "test" ["class"]=> string(6) "BtTest" ["type"]=> string(2) "->" ["args"]=> array(0) { } } } PHP Warning: assert(): Assertion "array_key_exists("line", $bti)" failed in /somewhere/in/the/filesystem/tests/bt-test-so.php on line 21 PHP Warning: assert(): Assertion "array_key_exists("file", $bti)" failed in /somewhere/in/the/filesystem/tests/bt-test-so.php on line 22
Первый элемент backtrace (индекс 0) косвенно указывает (через line
и элементы file
), что метод getTheItem
был вызван методом __call
.
Второй элемент backtrace (индекс 1) говорит, что метод __call
вызывался откуда- то (отсутствующие line
и элементы file
).
Третий элемент backtrace (индекс 2) говорит, что метод test
был вызван из глобальной области сценария.
Место __call
метода __call
, вероятно, находится в коде определения метода где-то в коде интерпретатора php. Есть две возможности ее фиксации. Либо второй элемент должен ссылаться на файл исходного кода интерпретатора и строку, либо на второй и третий элементы обратной линии должны быть объединены в один. Я лично предпочел бы второе решение, поскольку внутренности интерпретатора мне не интересны (так они кажутся ему в трассировке питона), однако я понимаю, что иногда первое решение обеспечивает более явный след (особенно когда это обратный вызов, который является вызванный из внутренних органов).
Так или иначе, кажется, что разработчик (разработчики), ответственный за (или, по крайней мере, поддерживающий) код функции debug_backtrace
, не воспринимает его как ошибку или, возможно, не имеет простого способа исправить это. Было бы нормально заполнить line
и file
с помощью значений места размещения (например, <unknown-file>
и 0
или даже null ) и подчеркнуть это в документации. Если кто-то не убедит их сделать это, вам просто нужно обработать специальный код в вашем коде.
Я написал выше, чтобы поделиться своим пониманием странного поведения функции. Если у кого-то есть желание бороться за немного лучший мир, вот ссылки на некоторые связанные отчеты об ошибках:
__FILE__
, __LINE__
Самый старый отчет – с 2003 года, поэтому вы не должны рассчитывать на быстрое решение 🙂
Я думаю, что это указано как ошибка PHP
Отладка backtrace показывает имя файла и lineno вызова сценария. В случае, если функция вызывается из внутренней внутренней функции (может быть как обратный вызов), никакие имя файла и lineno не могут быть установлены.
Независимо от любой «ошибки», «функции», независимо от того, что люди, поддерживающие PHP, хотели бы сказать, debug_backtrace () не работает так, как я ожидал.
Вот мое решение (это уродливо, но оно работает для меня):
function dbg($msg="") { ob_start(); debug_print_backtrace(0,1); $_ = ob_get_clean(); list($ignore,$line_number) = explode(':', $_); $line_number += 0; $backtrace = debug_backtrace(0); extract($backtrace[1]); echo "<pre>$class::$function($msg) : $line_number</pre>"; }
PHP-функция debug_print_backtrace (0,1); что-то вроде этого:
# 0 dbg-> ping (290), вызванный в [/path/to/filename.php:290]
Так как это только эхо след, я должен ob_get_clean () это как строка. Затем я разбираю его.
В моей реализации я хочу знать только класс, функцию, номер строки и, необязательно, строковое сообщение от вызывающей функции. debug_backtrace () обеспечивает класс и функцию правильно, но не номер строки. Вот почему я должен получить номер строки из функции debug_print_backtrace ().
Для бонусных очков …. как это, что функция debug_print_backtrace () «знает» номер строки, но debug_backtrace () [иногда] не делает, а? … это тайна…