简述
可能大家都知道,php中有一个函数叫debug_backtrace,它可以回溯跟踪函数的调用信息,可以说是一个调试利器。
好,来复习一下
01 one(); 02 03 function one() { 04 two(); 05 } 06 07 function two() { 08 three(); 09 } 10 11 function three() { 12 print_r( debug_backtrace() ); 13 } 14 15 /* 16 输出: 17 Array 18 ( 19 [0] => Array 20 ( 21 [file] => D:\apmserv\www\htdocs\test\debug\index.php 22 [line] => 10 23 [function] => three 24 [args] => Array 25 ( 26 ) 27 28 ) 29 30 [1] => Array 31 ( 32 [file] => D:\apmserv\www\htdocs\test\debug\index.php 33 [line] => 6 34 [function] => two 35 [args] => Array 36 ( 37 ) 38 39 ) 40 41 [2] => Array 42 ( 43 [file] => D:\apmserv\www\htdocs\test\debug\index.php 44 [line] => 3 45 [function] => one 46 [args] => Array 47 ( 48 ) 49 50 ) 51 52 ) 53 */
顺便提一下类似的函数:debug_print_backtrace,与之不同的是它会直接打印回溯信息。
回来看debug_backtrace,从名字来看用途很明确,是让开发者用来调试的。直到有一天我注意到它返回的file参数,file表示函数或者方法的调用脚本来源(在哪个脚本文件使用的)。忽然我想到,如果当前脚本知道调用来源,那是否可以根据这个来源的不同,来实现一些有趣的功能,比如文件权限管理、动态加载等。
实战
实现魔术函数
获取当前函数或方法的名称
尽管PHP中已经有了__FUNCTION__和__METHOD__魔术常量,但我还是想介绍一下用debug_backtrace获取当前函数或者方法名称的方法。
代码如下:
01 //函数外部输出getFuncName的值 02 echo getFuncName(); 03 04 printFuncName(); 05 06 Object::printMethodName(); 07 08 //调用了上面两个函数后,再次在外部输出getFuncName,看看是否有‘缓存’之类的问题 09 echo getFuncName(); 10 11 12 13 function printFuncName() { 14 echo getFuncName(); 15 } 16 17 class Object { 18 static function printMethodName() { 19 echo getFuncName(); 20 } 21 } 22 23 /** 24 * 获取当前函数或者方法的名称 25 * 函数名叫getFuncName,好吧,其实method也可以当做function,实在想不出好名字 26 * 27 * @return string name 28 */ 29 function getFuncName() { 30 $debug_backtrace = debug_backtrace(); 31 //如果函数名是以下几个,表示载入了脚本,并在函数外部调用了getFuncName 32 //这种情况应该返回空 33 $ignore = array( 34 'include', 35 'include_once', 36 'require', 37 'require_once' 38 ); 39 //第一个backtrace就是当前函数getFuncName,再上一个(第二个)backtrace就是调用getFuncName的函数了 40 $handle_func = $debug_backtrace[1]; 41 if( isset( $handle_func['function'] ) && !in_array( $handle_func['function'], $ignore ) ) { 42 return $handle_func['function']; 43 } 44 return null; 45 } 46 47 48 //输出: 49 //null 50 //printFuncName 51 //printMethodName 52 //null