如何找到构建页面所执行的函数列表?

发布于 2024-10-01 00:30:30 字数 375 浏览 3 评论 0原文

我想要执行到代码中某个点的所有函数的列表,有点像 debug_backtrace() 但包括不在调用 debug_backtrace() 的确切线程中的函数。例如 :

a();

function a() { 
 b();     
 c(); 
 d(); 
}

function b() { }
function c() { }
function d() { print all_trace(); }

会产生 : ,

a(), b(), c(), d()

而不是

a(), d()

像 debug_backtrace() 那样

I want the list of all functions executed to a certain point in code, somehow like debug_backtrace() but including functions not in the exact thread that leads to where debug_backtrace() is called. e.g :

a();

function a() { 
 b();     
 c(); 
 d(); 
}

function b() { }
function c() { }
function d() { print all_trace(); }

would produce :

a(), b(), c(), d()

and not

a(), d()

like debug_backtrace() would

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

空心↖ 2024-10-08 00:30:30

查看 xdebug 跟踪工具

check out xdebug tracing facility

∞觅青森が 2024-10-08 00:30:30

您可以安装 tick 处理程序,并在每个刻度上使用 debug_backtrace 查找您所在的函数并将其添加到列表中。它会降低性能,但会给出您想要的列表。

$functions_called=array();


function tick_handler()
{
    $trace=debug_backtrace();

    //we're in tick_handler, let's eat that
    array_shift($trace);

    //if we're in a function, log it!
    if (!empty($trace))
    {
        $function=$trace[0]['function'];

        //log function - lets just remember it was called
        global $functions_called;
        $functions_called[$function]=1;
    }
}

//install our tick handler...
declare(ticks=1);
register_tick_function('tick_handler');

下面是你如何获得你指定的输出:

function all_trace()
{
     global $functions_called;
     $output='';
     $separator='';
     foreach($functions_called as $func=>$dummy)
     {
          $output.=$separator.$func.'()';
          $separator=', ';
     }
     return $output;
}

真的很讨厌 - 正如其他人所建议的,最好使用像 xdebug 专为这项工作而设计,如果可以的话......

You could install a tick handler, and on every tick use debug_backtrace to find which function you are in and add it to a list. It will kill performance, but would give the list you desire.

$functions_called=array();


function tick_handler()
{
    $trace=debug_backtrace();

    //we're in tick_handler, let's eat that
    array_shift($trace);

    //if we're in a function, log it!
    if (!empty($trace))
    {
        $function=$trace[0]['function'];

        //log function - lets just remember it was called
        global $functions_called;
        $functions_called[$function]=1;
    }
}

//install our tick handler...
declare(ticks=1);
register_tick_function('tick_handler');

Here's how you'd get the output you specify from this:

function all_trace()
{
     global $functions_called;
     $output='';
     $separator='';
     foreach($functions_called as $func=>$dummy)
     {
          $output.=$separator.$func.'()';
          $separator=', ';
     }
     return $output;
}

Pretty nasty really - as others suggest, better to use tools like xdebug designed for the job if you can...

颜漓半夏 2024-10-08 00:30:30

服务器上不需要 Xdebug 或 dbg.so,返回更详细的消息,基于 Paul Dixon 的解决方案:

diyism_trace.php:

<?
define(TRACES_MODE, 'TEXTAREA');//'TEXTAREA' or 'FIREPHP' or 'TMPLOG'
$GLOBALS['traces.pre']=array();
function my_array_diff($arr1, $arr2)
         {foreach ($arr1 as $k=>$v)
                  {if (in_array($v, $arr2, true))
                      {unset($arr1[$k]);
                      }
                  }
          return $arr1;
         }
function my_var_export($var, $is_str=false)
         {$rtn=preg_replace(array('/Array\s+\(/', '/\[(\d+)\] => (.*)\n/', '/\[([^\d].*)\] => (.*)\n/'), array('array (', '\1 => \'\2\''."\n", '\'\1\' => \'\2\''."\n"), substr(print_r($var, true), 0, -1));
          $rtn=strtr($rtn, array("=> 'array ('"=>'=> array ('));
          $rtn=strtr($rtn, array(")\n\n"=>")\n"));
          $rtn=strtr($rtn, array("'\n"=>"',\n", ")\n"=>"),\n"));
          $rtn=preg_replace(array('/\n +/e'), array('strtr(\'\0\', array(\'    \'=>\'  \'))'), $rtn);
          $rtn=strtr($rtn, array(" Object',"=>" Object'<-"));
          if ($is_str)
             {return $rtn;
             }
          else
              {echo $rtn;
              }
         }
function tick_handler()
         {$tmp=debug_backtrace();
          $trace=my_array_diff($tmp, $GLOBALS['traces.pre']);
          //echo '<pre>';var_export($trace);echo '</pre>';echo '<br/>'; //for debug diyism_trace.php
          $trace=array_values($trace);
          $GLOBALS['traces.pre']=$tmp;
          $fun=@$tmp[1]['class'].@$tmp[1]['type'].@$tmp[1]['function'];
          if (count($trace)>0 && $trace[0]['file'].'/'.$fun!==@$GLOBALS['traces'][count($GLOBALS['traces'])-1]['key']) //filter empty array and rearrange array_values(), because some lines will trigger two tick events per line, for example: 1.last line is "some code;questmark>" 2.error_reporting(...
             {for ($i=count($trace)-1; $i>=0; --$i)
                  {$fun1=@$tmp[$i+1]['class'].@$tmp[$i+1]['type'].@$tmp[$i+1]['function'];
                   $fun2=$trace[$i]['class'].$trace[$i]['type'].$trace[$i]['function'];
                   $GLOBALS['traces'][]=$tmp_fb=array_merge(array('key'=>$trace[$i]['file'].'/'.$fun1),
                                                            $trace[$i],
                                                            array('function'=>strtr($fun2, array('tick_handler'=>'CONTINUE')), 'in_function'=>$fun1)
                                                           );
                   TRACES_MODE==='FIREPHP'?fb(trace_output($tmp_fb), 'diyism_trace:'.++$GLOBALS['diyism_trace_no']):'';
                  }
             }
         }
function trace_output($trace)
         {$trace['in_function']=strtr(@$trace['in_function'], array('require'=>'', 'require_once'=>'', 'include'=>'', 'include_once'=>''));
          $trace['args']=$trace['args']?strtr(preg_replace(array('/\n +/'), array(''), preg_replace(array('/\n  \d+ => /'), array(''), substr(my_var_export($trace['args'], true), 7, -3))), array("\r"=>'\r', "\n"=>'\n')):'';
          return $trace['file'].($trace['in_function']?'/'.$trace['in_function'].'()':'').'/'.$trace['line'].': '.$trace['function'].'('.$trace['args'].')';
         }
function traces_output()
         {$request_id=base_convert(time().substr(microtime(),2,6).mt_rand(), 10, 36);
          TRACES_MODE==='TEXTAREA'
          ?(print '<textarea style="width:100%;height:300px;">')
          :file_put_contents("/tmp/diyism_trace.{$request_id}.log", "==================".$_SERVER['REQUEST_URI'].":==================\n", FILE_APPEND);
          $GLOBALS['traces']=array_slice($GLOBALS['traces'], 2);//remove registering tick line and requiring 'diyism_trace.php' line
          foreach ($GLOBALS['traces'] as $k=>$trace)
                  {TRACES_MODE==='TEXTAREA'
                   ?(print htmlentities($k.':'.trace_output($trace)."\n"))
                   :file_put_contents("/tmp/diyism_trace.{$request_id}.log", $k.':'.trace_output($trace)."\n", FILE_APPEND);
                  }
          TRACES_MODE==='TEXTAREA'?(print '</textarea>'):'';
         }
register_tick_function('tick_handler');
(TRACES_MODE==='TEXTAREA' || TRACES_MODE==='TMPLOG')?register_shutdown_function('traces_output'):'';
?>

test.php:

<?
declare(ticks=1);
require 'diyism_trace.php';
a('a', array('hello'));
1+2;
b();
function a()
         {$d=1;
          b();
          $d=2;
          cls::c('cccc'); 
          $d=4;
          d(); 
          $d=5;
         }

function b()
         {1+1;
          d();
         }
class cls
      {static function c()
              {1+1;
              }
      }
function d()
         {1+1;
         }
?>

输出:

/var/www/test/test.php/3: CONTINUE()
/var/www/test/test.php/4: a('a',array (0 => 'hello',))
/var/www/test/test.php/a()/8: CONTINUE()
/var/www/test/test.php/a()/9: b()
/var/www/test/test.php/b()/18: CONTINUE()
/var/www/test/test.php/b()/19: d()
/var/www/test/test.php/d()/27: CONTINUE()
/var/www/test/test.php/b()/19: CONTINUE()
/var/www/test/test.php/a()/9: CONTINUE()
/var/www/test/test.php/a()/11: c('cccc')
/var/www/test/test.php/c()/23: CONTINUE()
/var/www/test/test.php/a()/11: CONTINUE()
/var/www/test/test.php/a()/13: d()
/var/www/test/test.php/d()/27: CONTINUE()
/var/www/test/test.php/a()/13: CONTINUE()
/var/www/test/test.php/4: CONTINUE()
/var/www/test/test.php/6: b()
/var/www/test/test.php/b()/18: CONTINUE()
/var/www/test/test.php/b()/19: d()
/var/www/test/test.php/d()/27: CONTINUE()
/var/www/test/test.php/b()/19: CONTINUE()
/var/www/test/test.php/6: CONTINUE()

need no Xdebug or dbg.so on server, return more detailed message, based on Paul Dixon's solution:

diyism_trace.php:

<?
define(TRACES_MODE, 'TEXTAREA');//'TEXTAREA' or 'FIREPHP' or 'TMPLOG'
$GLOBALS['traces.pre']=array();
function my_array_diff($arr1, $arr2)
         {foreach ($arr1 as $k=>$v)
                  {if (in_array($v, $arr2, true))
                      {unset($arr1[$k]);
                      }
                  }
          return $arr1;
         }
function my_var_export($var, $is_str=false)
         {$rtn=preg_replace(array('/Array\s+\(/', '/\[(\d+)\] => (.*)\n/', '/\[([^\d].*)\] => (.*)\n/'), array('array (', '\1 => \'\2\''."\n", '\'\1\' => \'\2\''."\n"), substr(print_r($var, true), 0, -1));
          $rtn=strtr($rtn, array("=> 'array ('"=>'=> array ('));
          $rtn=strtr($rtn, array(")\n\n"=>")\n"));
          $rtn=strtr($rtn, array("'\n"=>"',\n", ")\n"=>"),\n"));
          $rtn=preg_replace(array('/\n +/e'), array('strtr(\'\0\', array(\'    \'=>\'  \'))'), $rtn);
          $rtn=strtr($rtn, array(" Object',"=>" Object'<-"));
          if ($is_str)
             {return $rtn;
             }
          else
              {echo $rtn;
              }
         }
function tick_handler()
         {$tmp=debug_backtrace();
          $trace=my_array_diff($tmp, $GLOBALS['traces.pre']);
          //echo '<pre>';var_export($trace);echo '</pre>';echo '<br/>'; //for debug diyism_trace.php
          $trace=array_values($trace);
          $GLOBALS['traces.pre']=$tmp;
          $fun=@$tmp[1]['class'].@$tmp[1]['type'].@$tmp[1]['function'];
          if (count($trace)>0 && $trace[0]['file'].'/'.$fun!==@$GLOBALS['traces'][count($GLOBALS['traces'])-1]['key']) //filter empty array and rearrange array_values(), because some lines will trigger two tick events per line, for example: 1.last line is "some code;questmark>" 2.error_reporting(...
             {for ($i=count($trace)-1; $i>=0; --$i)
                  {$fun1=@$tmp[$i+1]['class'].@$tmp[$i+1]['type'].@$tmp[$i+1]['function'];
                   $fun2=$trace[$i]['class'].$trace[$i]['type'].$trace[$i]['function'];
                   $GLOBALS['traces'][]=$tmp_fb=array_merge(array('key'=>$trace[$i]['file'].'/'.$fun1),
                                                            $trace[$i],
                                                            array('function'=>strtr($fun2, array('tick_handler'=>'CONTINUE')), 'in_function'=>$fun1)
                                                           );
                   TRACES_MODE==='FIREPHP'?fb(trace_output($tmp_fb), 'diyism_trace:'.++$GLOBALS['diyism_trace_no']):'';
                  }
             }
         }
function trace_output($trace)
         {$trace['in_function']=strtr(@$trace['in_function'], array('require'=>'', 'require_once'=>'', 'include'=>'', 'include_once'=>''));
          $trace['args']=$trace['args']?strtr(preg_replace(array('/\n +/'), array(''), preg_replace(array('/\n  \d+ => /'), array(''), substr(my_var_export($trace['args'], true), 7, -3))), array("\r"=>'\r', "\n"=>'\n')):'';
          return $trace['file'].($trace['in_function']?'/'.$trace['in_function'].'()':'').'/'.$trace['line'].': '.$trace['function'].'('.$trace['args'].')';
         }
function traces_output()
         {$request_id=base_convert(time().substr(microtime(),2,6).mt_rand(), 10, 36);
          TRACES_MODE==='TEXTAREA'
          ?(print '<textarea style="width:100%;height:300px;">')
          :file_put_contents("/tmp/diyism_trace.{$request_id}.log", "==================".$_SERVER['REQUEST_URI'].":==================\n", FILE_APPEND);
          $GLOBALS['traces']=array_slice($GLOBALS['traces'], 2);//remove registering tick line and requiring 'diyism_trace.php' line
          foreach ($GLOBALS['traces'] as $k=>$trace)
                  {TRACES_MODE==='TEXTAREA'
                   ?(print htmlentities($k.':'.trace_output($trace)."\n"))
                   :file_put_contents("/tmp/diyism_trace.{$request_id}.log", $k.':'.trace_output($trace)."\n", FILE_APPEND);
                  }
          TRACES_MODE==='TEXTAREA'?(print '</textarea>'):'';
         }
register_tick_function('tick_handler');
(TRACES_MODE==='TEXTAREA' || TRACES_MODE==='TMPLOG')?register_shutdown_function('traces_output'):'';
?>

test.php:

<?
declare(ticks=1);
require 'diyism_trace.php';
a('a', array('hello'));
1+2;
b();
function a()
         {$d=1;
          b();
          $d=2;
          cls::c('cccc'); 
          $d=4;
          d(); 
          $d=5;
         }

function b()
         {1+1;
          d();
         }
class cls
      {static function c()
              {1+1;
              }
      }
function d()
         {1+1;
         }
?>

output:

/var/www/test/test.php/3: CONTINUE()
/var/www/test/test.php/4: a('a',array (0 => 'hello',))
/var/www/test/test.php/a()/8: CONTINUE()
/var/www/test/test.php/a()/9: b()
/var/www/test/test.php/b()/18: CONTINUE()
/var/www/test/test.php/b()/19: d()
/var/www/test/test.php/d()/27: CONTINUE()
/var/www/test/test.php/b()/19: CONTINUE()
/var/www/test/test.php/a()/9: CONTINUE()
/var/www/test/test.php/a()/11: c('cccc')
/var/www/test/test.php/c()/23: CONTINUE()
/var/www/test/test.php/a()/11: CONTINUE()
/var/www/test/test.php/a()/13: d()
/var/www/test/test.php/d()/27: CONTINUE()
/var/www/test/test.php/a()/13: CONTINUE()
/var/www/test/test.php/4: CONTINUE()
/var/www/test/test.php/6: b()
/var/www/test/test.php/b()/18: CONTINUE()
/var/www/test/test.php/b()/19: d()
/var/www/test/test.php/d()/27: CONTINUE()
/var/www/test/test.php/b()/19: CONTINUE()
/var/www/test/test.php/6: CONTINUE()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文