对于大多数编译型语言,如C、Java、C#,我们可以很方便的进行断点调试,但是PHP必须安装XDebug,并在编辑器中进行复杂的配置,才能实现断点调试的能力.但是,如果只是单纯的调试查看堆栈回溯,其实PHP已经为我们准备了两个函数,可以让我们在程序运行时非常方便的查看程序的调用状态。debug_backtrace()从这个方法的字面意思可以看出,它的意思是调试backtrace,返回的是一个backtrace信息数组。functiona_test($str){echo"Hi:$str",PHP_EOL;var_dump(debug_backtrace());}var_dump(debug_backtrace());a_test("A");//Hi:A/Users/zhangyue/MyDoc/blogpost/dev-blog/php/202004/source/PHPprinttracedebuginfo.php:7://array(1){//[0]=>//array(4){//'file'=>//string(93)"/Users/zhangyue/MyDoc/blogarticle/dev-blog/php/202004/source/PHP打印跟踪调试信息.php"//'line'=>//int(12)//'function'=>//string(6)"a_test"//'args'=>//array(1){//[0]=>//string(1)"A"//}//}//}这个方法必须在函数中调用,它会在函数方法之外使用时没有内容。从内容中输出\_\_FILE__,\_\_LINE__,\_\_FUNCTION__,$argv等关于这个函数的信息。其实就是打印当前行所在函数的相关内容。当然,我们也可以嵌套几层函数,看看打印出来的内容是什么。functionb_test(){c_test();}functionc_test(){a_test("b->c->a");}b_test();//Hi:b->c->a///Users/zhangyue/MyDoc/blogpost/dev-blog/php/202004/source/PHP打印跟踪调试信息.php:7://array(3){//[0]=>//array(4){//'file'=>//string(93)"/Users/zhangyue/MyDoc/blogarticle/dev-blog/php/202004/source/PHPprinttracedebugginginformation.php"//'line'=>//int(37)//'function'=>//string(6)"a_test"//'args'=>//array(1){//[0]=>//string(11)"b->c->a"//}//}//[1]=>//array(4){//'file'=>//string(93)"/Users/zhangyue/MyDoc/blogpost/dev-blog/php/202004/source/PHPprinttracedebugginginformation.php"//'line'=>//int(33)//'function'=>//string(6)"c_test"//'args'=>//array(0){//}//}//[2]=>//array(4){//'file'=>//string(93)"/Users/zhangyue/MyDoc/博客文章/dev-blog/php/202004/source/PHPprinttracedebuginfo.php"//'line'=>//int(40)//'function'=>//string(6)"b_test"//'args'=>//array(0){//}//}//}是的,输出顺序array是一个栈的执行顺序,b_test()先被调用,所以在栈底,对应的输出是数组的最后一个元素,在类中也有类似的用法.A类{函数test_a(){$this->test_b();}functiontest_b(){var_dump(debug_backtrace());}}$a=newA();$a->test_a();///Users/zhangyue/MyDoc/blogarticle/dev-blog/php/202004/source/PHP打印跟踪调试信息.php:90://array(2){//[0]=>//array(7){//'file'=>//string(93)"/Users/zhangyue/MyDoc/blogarticle/dev-blog/php/202004/source/PHP打印跟踪调试信息.php"//'line'=>//int(87)//'function'=>//string(6)"test_b"//'class'=>//string(1)"A"//'object'=>//classA#1(0){//}//'type'=>//string(2)"->"//'args'=>//array(0){//}//}//[1]=>//array(7){//'file'=>//string(93)"/Users/zhangyue/MyDoc/博客文章/dev-blog/php/202004/source/PHP打印跟踪调试信息.php"//'line'=>//int(95)//'function'=>//string(6)"test_a"//'class'=>//string(1)"A"//'object'=>//classA#1(0){//}//'type'=>//string(2)"->"//'args'=>//array(0){//}//}//}在类中使用时,数组项会有一个额外的对象字段,它显示了这个方法所在的类的信息。debug_backtrace()的函数声明为:debug_backtrace([int$options=DEBUG_BACKTRACE_PROVIDE_OBJECT[,int$limit=0]]):arraywhere\$options有两个常量可以定义,DEBUG_BACKTRACE_PROVIDE_OBJECT表示是否填充“对象”指数;DEBUG_BACKTRACE_IGNORE_ARGS是否忽略“args”索引,包括所有函数/方法参数,可以节省内存开销。$limits可用于限制返回堆栈帧的数量,默认为0返回所有堆栈。debug_backtrace()和下面要介绍的debug_print_backtrace()方法支持在eval()中require/include文件和代码。嵌入文件时,会输出嵌入文件的路径。你可以自己试试这个。debug_print_backtrace()方法从名字也可以看出,它会直接打印backtrace的内容,它的函数声明和debug_backtrace()一样,但是$options默认为DEBUG_BACKTRACE_IGNORE_ARGS,也就是说它只打印文件和呼叫所在的线路号码。functiona(){b();}functionb(){c();}functionc(){debug_print_backtrace();}a();#0c()调用于[/Users/zhangyue/MyDoc/blog文章/dev-blog/php/202004/source/PHPprinttracedebugginginformation.php:144]#1b()calledat[/Users/zhangyue/MyDoc/blogarticle/dev-blog/php/202004/source/PHPprinttracedebuginformation.php:140]#2a()calledat[/Users/zhangyue/MyDoc/blogarticle/dev-blog/php/202004/source/PHPprinttracedebuginformation.php:151]其他是这个函数输出不需要用到var_dump()或者print_r(),直接用这个函数输出。非常方便我们调试。比如在laravel这样的大型框架中,当我们需要在controller中查看栈信息时,可以使用debug_print_backtrace()来快速查看当前的栈调用情况。但是如果debug_backtrace()没有指定$options,会占用非常大的内存容量或者无法完整显示。小结今天介绍的两个函数可以灵活的帮助我们调试代码或者理解一个框架的调用。当然,正式场合还是建议使用Xdebug加上编辑器支持断点调试,因为使用debug_backtrace()这两个方法我们看不到变量的变化。测试代码:https://github.com/zhangyue0503/dev-blog/blob/master/php/202004/source/PHP%E6%89%93%E5%8D%B0%E8%B7%9F%E8%B8%AA%E8%B0%83%E8%AF%95%E4%BF%A1%E6%81%AF.php参考文档:https://www.php.net/manual/zh/function.debug-backtrace.phphttps://www.php.net/manual/zh/function.debug-print-backtrace.php各媒体平台均可搜索【硬核项目经理】
