对于大部分编译型语言来说,比方 C 、 Java 、 C# ,咱们都能很不便地进行断点调试,然而 PHP 则必须装置 XDebug 并且在编辑器中进行简单的配置能力实现断点调试的能力。不过,如果只是简略的调试并且查看堆栈回溯的话,其实 PHP 曾经为咱们筹备好了两个函数,可能让咱们十分不便的看到程序运行时的调用状况。

debug_backtrace()

从这个办法的字面意思上就能够看出,它的意思就是调试回溯,返回的也正是一段回溯信息的数组。

function a_test($str){    echo "Hi: $str", PHP_EOL;    var_dump(debug_backtrace());}var_dump(debug_backtrace());a_test("A");// Hi: A/Users/zhangyue/MyDoc/博客文章/dev-blog/php/202004/source/PHP打印跟踪调试信息.php:7:// array(1) {//   [0] =>//   array(4) {//     'file' =>//     string(93) "/Users/zhangyue/MyDoc/博客文章/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 等信息。其实就是对于以后打印这行所在函数的相干内容。

咱们当然也能够多嵌套几层函数来看一下打印出的内容是什么。

function b_test(){    c_test();}function c_test(){    a_test("b -> c -> a");}b_test();// Hi: b -> c -> a// /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202004/source/PHP打印跟踪调试信息.php:7:// array(3) {//   [0] =>//   array(4) {//     'file' =>//     string(93) "/Users/zhangyue/MyDoc/博客文章/dev-blog/php/202004/source/PHP打印跟踪调试信息.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/博客文章/dev-blog/php/202004/source/PHP打印跟踪调试信息.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/PHP打印跟踪调试信息.php"//     'line' =>//     int(40)//     'function' =>//     string(6) "b_test"//     'args' =>//     array(0) {//     }//   }// }

没错,数组的输入程序就是一个栈的执行程序,b_test() 最先调用,所以它在栈底,对应的输入也就是数组中的最初一个元素。

在类中也是相似的应用办法。

class A{    function test_a(){        $this->test_b();    }    function test_b(){        var_dump(debug_backtrace());    }}$a = new A();$a->test_a();// /Users/zhangyue/MyDoc/博客文章/dev-blog/php/202004/source/PHP打印跟踪调试信息.php:90:// array(2) {//   [0] =>//   array(7) {//     'file' =>//     string(93) "/Users/zhangyue/MyDoc/博客文章/dev-blog/php/202004/source/PHP打印跟踪调试信息.php"//     'line' =>//     int(87)//     'function' =>//     string(6) "test_b"//     'class' =>//     string(1) "A"//     'object' =>//     class A#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' =>//     class A#1 (0) {//     }//     'type' =>//     string(2) "->"//     'args' =>//     array(0) {//     }//   }// }

在类中应用的时候,在数组项中会多出一个 object 字段,显示的是这个办法所在类的信息。

debug_backtrace() 的函数申明是:

debug_backtrace ([ int $options = DEBUG_BACKTRACE_PROVIDE_OBJECT [, int $limit = 0 ]] ) : array

其中 \$options 是有两个常量能够定义,DEBUG_BACKTRACE_PROVIDE_OBJECT 表明是否填充 "object" 的索引;DEBUG_BACKTRACE_IGNORE_ARGS 是否疏忽 "args" 的索引,包含所有的 function/method 的参数,可能节俭内存开销。 $limits 可用于限度返回堆栈帧的数量,默认为0返回所有的堆栈。

debug_backtrace() 以及上面要介绍的 debug_print_backtrace() 办法都是反对 require/include 文件以及 eval() 中的代码的,在嵌入文件时,会输入嵌入文件的门路,这个大家能够自行尝试。

debug_print_backtrace()

这个办法从名称也能够看出,它会间接打印回溯内容,它的函数申明和 debug_backtrace() 是一样的,不过 $options 默认是 DEBUG_BACKTRACE_IGNORE_ARGS ,也就是说,它只打印调用所在文件及行数。

function a() {    b();}function b() {    c();}function c(){    debug_print_backtrace();}a();#0  c() called at [/Users/zhangyue/MyDoc/博客文章/dev-blog/php/202004/source/PHP打印跟踪调试信息.php:144]#1  b() called at [/Users/zhangyue/MyDoc/博客文章/dev-blog/php/202004/source/PHP打印跟踪调试信息.php:140]#2  a() called at [/Users/zhangyue/MyDoc/博客文章/dev-blog/php/202004/source/PHP打印跟踪调试信息.php:151]

另外就是这个函数不须要应用 var_dump() 或 print_r() 进行输入,间接应用这个函数就会进行输入。可能十分快捷不便的让咱们进行调试,比方在 laravel 这类大型框架中,咱们在控制器须要查看堆栈信息时,就能够应用 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.php

https://www.php.net/manual/zh/function.debug-print-backtrace.php

各自媒体平台均可搜寻【硬核项目经理】