【问题标题】:php: determine where function was called fromphp:确定从哪里调用函数
【发布时间】:2010-06-02 19:09:34
【问题描述】:

有没有办法找出 PHP 中的函数是从哪里调用的? 示例:

function epic()
{
  fail();
}

function fail()
{
  //at this point, how do i know, that epic() has called this function?
}

【问题讨论】:

    标签: php function-calls


    【解决方案1】:

    您可以使用debug_backtrace()

    示例:

    <?php
    
    function epic( $a, $b )
    {
        fail( $a . ' ' . $b );
    }
    
    function fail( $string )
    {
        $backtrace = debug_backtrace();
    
        print_r( $backtrace );
    }
    
    epic( 'Hello', 'World' );
    

    输出:

    Array
    (
        [0] => Array
            (
                [file] => /Users/romac/Desktop/test.php
                [line] => 5
                [function] => fail
                [args] => Array
                    (
                        [0] => Hello World
                    )
    
            )
    
        [1] => Array
            (
                [file] => /Users/romac/Desktop/test.php
                [line] => 15
                [function] => epic
                [args] => Array
                    (
                        [0] => Hello
                        [1] => World
                    )
    
            )
    
    )
    

    【讨论】:

    • 我第一次发现debug_backtrace() 多么棒的功能。我会用这个!
    【解决方案2】:

    使用debug_backtrace():

    function fail()
    {
        $backtrace = debug_backtrace();
    
        // Here, $backtrace[0] points to fail(), so we'll look in $backtrace[1] instead
        if (isset($backtrace[1]['function']) && $backtrace[1]['function'] == 'epic')
        {
            // Called by epic()...
        }
    }
    

    【讨论】:

    • 这绝对是你想要的。但请注意debug_backtrace() 是一个昂贵的电话。不要养成使用它来确定调用链的习惯。如果您想“保护”这些功能,请查看 OOP 和受保护的方法。
    【解决方案3】:

    我发现的最快和最简单的解决方案

    public function func() { //function whose call file you want to find
        $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
    }
    
    $trace: Array
    (
        [0] => Array
            (
                [file] => C:\wamp\www\index.php
                [line] => 56
                [function] => func
                [class] => (func Class namespace)
                [type] => ->
            )
    
    )
    

    我在联想笔记本电脑上测试速度:Intel Peniom CPU N3530 2.16GHz,RAM 8GB

    global $times;
    $start = microtime(true);
    $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
    $times[] = microtime(true) - $start;
    

    结果:

    count($times):  97
    min:    2.6941299438477E-5
    max:   10.68115234375E-5
    avg:    3.3095939872191E-5
    median: 3.0517578125E-5
    sum:  321.03061676025E-5
    
    the same results with notation without E-5
    count($times):  97
    min:    0.000026941299438477
    max:    0.0001068115234375
    avg:    0.000033095939872191
    median: 0.000030517578125
    sum:    0.0032103061676025
    

    【讨论】:

    • 对我来说 DEBUG_BACKTRACE_IGNORE_ARGS 非常有用,如果没有它,信息就会太多。
    【解决方案4】:

    因此,如果您仍然真的不知道如何,那么这里是解决方案:

    $backtrace = debug_backtrace();
    echo 'Mu name is '.$backtrace[1]['function'].', and I have called him! Muahahah!';
    

    【讨论】:

    • 所以你可以使用 if($backtrace[1]['function'] == 'epic') { // 做一些事情; else 做一些其他的事情; ??哇
    • 是的,但不要!无论如何,不​​在永久应用程序代码中。使用参数。 debug_backtrace() 看起来是一个相当繁重的操作。
    【解决方案5】:

    【讨论】:

      【解决方案6】:

      试试下面的代码。

      foreach(debug_backtrace() as $t) {              
         echo $t['file'] . ' line ' . $t['line'] . ' calls ' . $t['function'] . "()<br/>";
      }
      

      【讨论】:

      • 良好而直接的解决方案,可以追溯调用特定函数的所有文件。
      • 这是唯一对我有用的。谢谢!
      【解决方案7】:

      如果您想在堆栈顶部跟踪调用的确切来源,可以使用以下代码:

      $call_origin = end(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS));
      

      这将忽略链式函数并仅获取最相关的调用信息(相关使用松散,因为它取决于您要完成的任务)。

      【讨论】:

      • 谢谢。这为我节省了很多时间:)
      【解决方案8】:
      function findFunction($function, $inputDirectory=""){
          //version 0.1
          $docRoot = getenv("DOCUMENT_ROOT");
          $folderArray = null;
          $dirArray = null;
      
          // open directory
          $directory = opendir($docRoot.$inputDirectory);
      
          // get each entry
          while($entryName = readdir($directory)) {
              if(is_dir($entryName) && $entryName != "." && $entryName != ".."){
                  $folderArray[] = str_replace($inputDirectory, "", $entryName);
              }
              $ext = explode(".", $entryName);
              if(!empty($ext[1])){
                  $dirArray[] = $docRoot.$inputDirectory."/".$entryName;
              }
          }
      
          // close directory
          closedir($directory);
          $found = false;
      
          if(is_array($dirArray)){
              foreach($dirArray as $current){
                  $myFile = file_get_contents($current);
                  $myFile = str_replace("<?php", "", $myFile);
                  $myFile = str_replace("?>", "", $myFile);
                  if(preg_match("/function ".$function."/", $myFile)){
                      $found = true;
                      $foundLocation = $current;
                      break;
                  }
              }
          }
          if($found){
              echo $foundLocation;
              exit;
          } else if(is_array($folderArray)){
              foreach($folderArray as $folder){
                  if(!isset($return)){
                      $return = findFunction($function, $inputDirectory."/".$folder);
                  } else if($return == false){
                      $return = findFunction($function, $inputDirectory."/".$folder);
                  }
              }
          } else {
              return false;
          }
      }
      
      findFunction("testFunction", "rootDirectory");
      

      希望它可以帮助某人。如果实际功能在 httpdocs 之外,则无法找到它,因为服务器将设置为不允许它。也只测试了一个文件夹,但递归方法在理论上应该有效。

      这类似于 0.1 版,但我不打算继续开发它,所以如果有人更新,请随时重新发布。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-13
      • 1970-01-01
      • 2010-12-19
      • 2021-08-07
      • 1970-01-01
      • 2012-07-02
      • 1970-01-01
      • 2015-12-21
      相关资源
      最近更新 更多