【问题标题】:Get name of caller function in PHP?在 PHP 中获取调用者函数的名称?
【发布时间】:2008-10-10 07:31:47
【问题描述】:

是否有 PHP 函数可以找出给定函数中调用者函数的名称?

【问题讨论】:

  • 你应该使用 Xdebug。在这篇文章中查看我的答案:stackoverflow.com/questions/1513069/…
  • Xdebug 绝对不仅仅是一个 PHP 函数,它是原始请求。如果你想例如在后面的 PHP 逻辑中使用调用者函数名,而不是在生产服务器上安装 XDebug,你需要一个 PHP 函数。

标签: php


【解决方案1】:

请参阅debug_backtrace - 这可以将您的调用堆栈一直跟踪到顶部。

以下是您获取来电者的方式:

$trace = debug_backtrace();
$caller = $trace[1];

echo "Called by {$caller['function']}";
if (isset($caller['class']))
    echo " in {$caller['class']}";

【讨论】:

  • 在我看来,这会打印被调用函数名称。使用list(, $caller) = debug_backtrace(false); 获取调用者,使用false 获取性能;-) (php5.3)
  • 网上看到的很多解决方案都是通过backtrace数组的第二个元素来获取实例调用者:我们能这么确定吗?第二个元素总是我们要寻找的元素吗?我认为 __construct() 包含在另一个调用中,例如 parent::__construct() 可以移动另一个位置,真正的调用者(还没有尝试过)。
  • 我尝试在使用 ReflectionClass 时检查返回的调用者的顺序,它显然改变了“真实”调用者方法的位置,该方法在用户界面中可见,因此不假设回溯可以定位。
  • 数组移位将删除第一个元素并返回删除的元素。原始数组将被修改,这应该会给出所需的结果echo 'called by '.$trace[0]['function']
  • debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['function']; 获取性能更好的来电者姓名。
【解决方案2】:

Xdebug 提供了一些不错的功能。

<?php
  Class MyClass
  {
    function __construct(){
        $this->callee();
    }
    function callee() {
        echo sprintf("callee() called @ %s: %s from %s::%s",
            xdebug_call_file(),
            xdebug_call_line(),
            xdebug_call_class(),
            xdebug_call_function()
        );
    }
  }
  $rollDebug = new MyClass();
?>

将返回跟踪

callee() called @ /var/www/xd.php: 16 from MyClass::__construct

在 ubuntu 上安装 Xdebug 最好的方法是

sudo aptitude install php5-xdebug

你可能需要先安装 php5-dev

sudo aptitude install php5-dev

more info

【讨论】:

    【解决方案3】:

    这已经很晚了,但我想分享一个函数,它会给出调用当前函数的函数的名称。

    public function getCallingFunctionName($completeTrace=false)
        {
            $trace=debug_backtrace();
            if($completeTrace)
            {
                $str = '';
                foreach($trace as $caller)
                {
                    $str .= " -- Called by {$caller['function']}";
                    if (isset($caller['class']))
                        $str .= " From Class {$caller['class']}";
                }
            }
            else
            {
                $caller=$trace[2];
                $str = "Called by {$caller['function']}";
                if (isset($caller['class']))
                    $str .= " From Class {$caller['class']}";
            }
            return $str;
        }
    

    我希望这会有用。

    【讨论】:

    • “完整跟踪”模式非常有用。感谢分享。
    【解决方案4】:

    debug_backtrace() 提供当前调用堆栈中的参数、函数/方法调用的详细信息。

    【讨论】:

      【解决方案5】:
      echo debug_backtrace()[1]['function'];
      

      PHP 5.4开始工作。

      或优化(例如,用于非调试用例):

      echo debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['function'];
      

      第一个参数防止填充未使用的函数参数,第二个将跟踪限制为两个级别(我们需要第二个)。

      【讨论】:

        【解决方案6】:

        自己制作并使用它

        /**
         * Gets the caller of the function where this function is called from
         * @param string what to return? (Leave empty to get all, or specify: "class", "function", "line", "class", etc.) - options see: http://php.net/manual/en/function.debug-backtrace.php
         */
        function getCaller($what = NULL)
        {
            $trace = debug_backtrace();
            $previousCall = $trace[2]; // 0 is this call, 1 is call in previous function, 2 is caller of that function
        
            if(isset($what))
            {
                return $previousCall[$what];
            }
            else
            {
                return $previousCall;
            }   
        }
        

        【讨论】:

          【解决方案7】:

          我只是想说明 flori 的方式不能作为函数工作,因为它总是会返回被调用的函数名而不是调用者,但我没有评论的声誉。我根据弗洛里的回答做了一个非常简单的函数,它适用于我的情况:

          class basicFunctions{
          
              public function getCallerFunction(){
                  return debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]['function'];
              }
          
          }
          

          示例:

          function a($authorisedFunctionsList = array("b")){
              $ref = new basicFunctions;
              $caller = $ref->getCallerFunction();
          
              if(in_array($caller,$authorisedFunctionsList)):
                  echo "Welcome!";
                  return true;
              else:
                  echo "Unauthorised caller!";
                  return false; 
              endif;
          }
          
          function b(){
              $executionContinues = $this->a();
              $executionContinues or exit;
          
              //Do something else..
          }
          

          【讨论】:

            【解决方案8】:

            您可以从debug_backtrace返回的数组中提取此信息

            【讨论】:

              【解决方案9】:

              这个最适合我:var_dump(debug_backtrace());

              【讨论】:

                【解决方案10】:

                实际上,我认为 debug_print_backtrace() 可以满足您的需求。 http://php.net/manual/en/function.debug-print-backtrace.php

                【讨论】:

                  【解决方案11】:

                  这应该可行:

                  $caller = next(debug_backtrace())['function'];
                  

                  【讨论】:

                    【解决方案12】:

                    这会做得很好:

                    
                    // Outputs an easy to read call trace
                    // Credit: https://www.php.net/manual/en/function.debug-backtrace.php#112238
                    // Gist: https://gist.github.com/UVLabs/692e542d3b53e079d36bc53b4ea20a4b
                    
                    Class MyClass{
                    
                    public function generateCallTrace()
                    {
                        $e = new Exception();
                        $trace = explode("\n", $e->getTraceAsString());
                        // reverse array to make steps line up chronologically
                        $trace = array_reverse($trace);
                        array_shift($trace); // remove {main}
                        array_pop($trace); // remove call to this method
                        $length = count($trace);
                        $result = array();
                       
                        for ($i = 0; $i < $length; $i++)
                        {
                            $result[] = ($i + 1)  . ')' . substr($trace[$i], strpos($trace[$i], ' ')); // replace '#someNum' with '$i)', set the right ordering
                        }
                       
                        return "\t" . implode("\n\t", $result);
                    }
                    
                    }
                    
                    // call function where needed to output call trace
                    
                    /**
                    Example output:
                    1) /var/www/test/test.php(15): SomeClass->__construct()
                    2) /var/www/test/SomeClass.class.php(36): SomeClass->callSomething()
                    **/```
                    

                    【讨论】:

                      【解决方案13】:

                      我创建了一个泛型类,它对许多希望以用户可读的方式查看调用者方法的跟踪的人很有帮助。在我的一个项目中,我们需要记录这些信息。

                      use ReflectionClass;
                      
                      class DebugUtils
                      {
                          /**
                           * Generates debug traces in user readable form
                           *
                           * @param integer $steps
                           * @param boolean $skipFirstEntry
                           * @param boolean $withoutNamespaces
                           * @return string
                           */
                          public static function getReadableBackTracke(
                              $steps = 4,
                              $skipFirstEntry = true,
                              $withoutNamespaces = true
                          ) {
                              $str = '';
                              try {
                                  $backtrace = debug_backtrace(false, $steps);
                      
                                  // Removing first array entry
                                  // to make sure getReadableBackTracke() method doesn't gets displayed
                                  if ($skipFirstEntry)
                                      array_shift($backtrace);
                      
                                  // Reserved, so it gets displayed in calling order
                                  $backtrace = array_reverse($backtrace);
                      
                                  foreach ($backtrace as $caller) {
                                      if ($str) {
                                          $str .= ' --> ';
                                      }
                                      if (isset($caller['class'])) {
                                          $class = $caller['class'];
                                          if ($withoutNamespaces) {
                                              $class = (new ReflectionClass($class))->getShortName();
                                          }
                                          $str .= $class . $caller['type'];
                                      }
                                      $str .= $caller['function'];
                                  }
                              } catch (\Throwable $th) {
                                  return null;
                              }
                      
                              return $str;
                          }
                      }
                      

                      用法:DebugUtils::getReadableBackTracke()

                      样本输出:

                      SomeClass->method1 --> SomeOtherClass->method2 --> TargetClass->targetMethod
                      

                      做好事并继续帮助他人,快乐编码:)

                      【讨论】:

                        猜你喜欢
                        • 2010-10-28
                        • 1970-01-01
                        • 2022-12-10
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多