Ответ 1
Рассмотрим следующий код:
<?
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
вызывается из глобальной области script.
Место вызова метода __call
, вероятно, находится в коде кода разрешения кода где-то в коде интерпретатора php. Есть две возможности ее фиксации. Либо второй элемент должен ссылаться на файл исходного кода интерпретатора и строку, либо на второй и третий элементы backtrace должны быть объединены в один. Я лично предпочел бы второе решение, поскольку внутренности интерпретатора мне неинтересны (так они кажутся для этого в python traceback), однако я понимаю, что иногда первое решение обеспечивает более явный след (особенно когда это обратный вызов, который вызванный из внутренних элементов).
Так или иначе, кажется, что разработчик (разработчики), ответственный за (или, по крайней мере, поддерживающий) код функции debug_backtrace
, не воспринимает его как ошибку или, возможно, не имеет легкого способа его исправить. Было бы нормально заполнить элементы line
и file
некоторыми значениями держателя места (например, <unknown-file>
и 0
или даже null) и подчеркнуть его в документации. Если кто-то не убедит их сделать это, вам просто нужно обработать специальный код в вашем коде.
Я написал выше, чтобы поделиться своим пониманием странного поведения функции. Если у кого-то есть желание бороться за немного лучше мир, вот ссылки на некоторые связанные отчеты об ошибках:
- # 39070 вывод debug_backtrace при вызове call_user_func или обработчике ошибок
- # 24214 debug_backtrace() не сообщает
__FILE__
,__LINE__
- # 24405 debug_backtrace - отсутствует информация
- # 38047 "файл" и "строка" иногда не устанавливаются в обратном направлении из внутреннего обработчика ошибок
- # 44428 "файл" и "строка" отсутствуют в файле debug_backtrace()
Самый старый отчет - с 2003 года, поэтому вы не должны рассчитывать на быстрое исправление:)