我发现有时候debug_backtrace()
不包括来电号码。有什么理由可以解决这个问题吗?
提前致谢。
P.S。是的,省略行号的调用是我自己的代码,而不是内部PHP代码。
答案 0 :(得分:11)
请考虑以下代码:
<?
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
第一个回溯项(索引0)间接(通过line
和file
个项目)表示从getTheItem
方法调用__call
方法。
第二个回溯项(索引1)表示从某处调用了__call
方法(缺少line
和file
个项目。)
第三个回溯项(索引2)表示从脚本的全局范围调用test
方法。
__call
方法调用的位置可能在php解释器代码中的某些方法解析代码中。修复它有两种可能性。第二个项目应该引用解释器的源代码文件和行,或者第二个和第三个回溯项目应该合并为一个。我个人更喜欢第二种解决方案,因为解释器的内部结构对我来说并不感兴趣(这就是他们在python的追溯中的表现),但是我知道有时第一种解决方案提供了更明确的跟踪(特别是当它是一个回调时,它是从内部调用。)
左右,似乎负责(或至少维护)debug_backtrace
函数代码的开发人员并不认为它是一个bug或者没有简单的方法来解决它。可以使用一些占位符值(例如line
和file
或甚至 nulls )填充<unknown-file>
和0
项并强调它在文档中。 除非有人成功说服他们这样做,否则你只需要处理代码中的特殊情况。
我上面写的只是为了分享我对函数奇怪行为的理解。如果有人愿意为更好的世界而战,那么这里有一些相关错误报告的链接:
__FILE__
, __LINE__
最早的报告来自2003年,所以你不应指望快速修复:)
答案 1 :(得分:4)
我认为这被列为PHP Bug
调试回溯显示文件名和 调用脚本的lineno。如果 函数从内部调用 内部函数(可能作为回调) 没有文件名和lineno可以设置。
答案 2 :(得分:1)
无论任何“错误”,“功能”,无论维护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-&gt; ping(290)调用[/path/to/filename.php:290]
因为它只回显了跟踪,所以我必须将ob_get_clean()作为一个字符串。然后我解析它。
在我的实现中,我只想知道调用函数的类,函数,行号和(可选)字符串消息。 debug_backtrace()正确提供类和函数,但不提供行号。这就是为什么我必须从debug_print_backtrace()函数中获取行号。
对于奖励积分....如何调试debug_print_backtrace()函数“知道”行号,但是debug_backtrace()[偶尔]不会,呃??? ......这是一个谜......
答案 3 :(得分:1)
在各种 PHP 版本的 bugs.php.net 上检查了一堆相关问题后,这个问题似乎已经在 PHP 7.0 及更高版本上得到修复,包括 8.0,它总是提供一个“文件”,即使它是假的像从 stdin 评估的代码的“标准输入代码”。