【问题标题】:How can I get the full string of PHP’s getTraceAsString()?如何获取 PHP 的 getTraceAsString() 的完整字符串?
【发布时间】:2010-12-29 07:01:07
【问题描述】:

我正在使用getTraceAsString() 获取堆栈跟踪,但由于某种原因字符串被截断。

例如,抛出异常,我使用以下命令记录字符串:

catch (SoapFault $e) {
error_log( $e->getTraceAsString() )
}

打印出来的字符串是:

#0 C:\Somedirectory\Somedirectory\Somedirectory\Somedir\SomeScript.php(10): SoapClient->SoapClient('http://www.ex...')

如何打印完整的字符串?

【问题讨论】:

  • 嗨。很久很久以前,你在这里得到了一些很好的帮助。您介意接受答案,甚至发布您自己的答案吗?谢谢。

标签: php string exception truncation truncated


【解决方案1】:

我创建了这个函数来返回一个没有截断字符串的堆栈跟踪:

function getExceptionTraceAsString($exception) {
    $rtn = "";
    $count = 0;
    foreach ($exception->getTrace() as $frame) {
        $args = "";
        if (isset($frame['args'])) {
            $args = array();
            foreach ($frame['args'] as $arg) {
                if (is_string($arg)) {
                    $args[] = "'" . $arg . "'";
                } elseif (is_array($arg)) {
                    $args[] = "Array";
                } elseif (is_null($arg)) {
                    $args[] = 'NULL';
                } elseif (is_bool($arg)) {
                    $args[] = ($arg) ? "true" : "false";
                } elseif (is_object($arg)) {
                    $args[] = get_class($arg);
                } elseif (is_resource($arg)) {
                    $args[] = get_resource_type($arg);
                } else {
                    $args[] = $arg;
                }   
            }   
            $args = join(", ", $args);
        }
        $rtn .= sprintf(
            "#%s %s(%s): %s%s%s(%s)\n",
            $count,
            $frame['file'],
            $frame['line'],
            isset($frame['class']) ? $frame['class'] : '',
            isset($frame['type']) ? $frame['type'] : '', // "->" or "::"
            $frame['function'],
            $args
        );
        $count++;
    }
    return $rtn;
}

或者,您可以编辑截断输出的 php 源代码:https://github.com/php/php-src/blob/master/Zend/zend_exceptions.c#L392

【讨论】:

  • 感谢这个功能。很有用。 Exception 中回溯的截断多年来一直困扰着我,但我从来没有时间对此做任何事情。我现在将您的函数添加到lampcms.com 上的核心异常类中。
  • 谢谢史蒂夫。我添加了一些跨度用于颜色编码,我们正在做生意,例如:$rtn .= sprintf("#%s %s(%s): %s(%s)\n",
  • 谢谢。然而,当我尝试它时,我收到了两条通知:Notice: Undefined index: fileNotice: Undefined index: line
  • 为什么不将json_encode() 用于异常跟踪数组?
  • 请注意,有一个新的 INI 指令 (zend.exception_ignore_args) 用于在异常生成的堆栈跟踪中包含或排除参数。来源:php.net/manual/de/migration74.other-changes.php 确保将其设置为 0,例如像这样:ini_set('zend.exception_ignore_args', 0);
【解决方案2】:

该解决方案很好,但在我的情况下它引发了错误,因为我的跟踪中有内部函数。我添加了几行代码来检查这一点,因此跟踪功能仍然有效。

function getExceptionTraceAsString($exception) {
    $rtn = "";
    $count = 0;
    foreach ($exception->getTrace() as $frame) {


        $args = "";
        if (isset($frame['args'])) {
            $args = array();
            foreach ($frame['args'] as $arg) {
                if (is_string($arg)) {
                    $args[] = "'" . $arg . "'";
                } elseif (is_array($arg)) {
                    $args[] = "Array";
                } elseif (is_null($arg)) {
                    $args[] = 'NULL';
                } elseif (is_bool($arg)) {
                    $args[] = ($arg) ? "true" : "false";
                } elseif (is_object($arg)) {
                    $args[] = get_class($arg);
                } elseif (is_resource($arg)) {
                    $args[] = get_resource_type($arg);
                } else {
                    $args[] = $arg;
                }
            }
            $args = join(", ", $args);
        }
        $current_file = "[internal function]";
        if(isset($frame['file']))
        {
            $current_file = $frame['file'];
        }
        $current_line = "";
        if(isset($frame['line']))
        {
            $current_line = $frame['line'];
        }
        $rtn .= sprintf( "#%s %s(%s): %s(%s)\n",
            $count,
            $current_file,
            $current_line,
            $frame['function'],
            $args );
        $count++;
    }
    return $rtn;
}

【讨论】:

    【解决方案3】:

    一些更好的版本https://stackoverflow.com/a/6076667/194508 在这里https://gist.github.com/1437966 为输出添加了类。

    【讨论】:

      【解决方案4】:

      更改 php.ini 设置 log_errors_max_len 会有帮助吗?

      另外,请注意消息仅在输出期间被截断,您仍然可以通过调用 $exception->getMessage() 获得原始错误消息

      【讨论】:

      • 在创建这篇文章之前,我将 log_errors_max_len 的值从 1024 提高到 4096。但没有区别。
      • 关于 getMessage(),我同时使用 getMessage() 和 getTraceAsString(),但它们打印的内容不同,所以我都需要它们。
      • 这对于完整的getTraceAsString() 输出是不够的
      • 这只是解决了我遇到的一个问题。未捕获的异常受此设置的约束(但字符串化异常没有此问题)。
      【解决方案5】:

      还有由 Ernest Vogelsinger 在https://www.php.net/manual/exception.gettraceasstring.php#114980 编写的出色的jTraceEx 配方,它支持链式异常并以类似 Java 的方式进行格式化。

      这是直接取自他在 php.net 上的评论的比较:

      异常::getTraceAsString :

      #0 /var/htdocs/websites/sbdevel/public/index.php(70): seabird\test\C->exc()
      #1 /var/htdocs/websites/sbdevel/public/index.php(85): seabird\test\C->doexc()
      #2 /var/htdocs/websites/sbdevel/public/index.php(89): seabird\test\fail2()
      #3 /var/htdocs/websites/sbdevel/public/index.php(93): seabird\test\fail1()
      #4 {main}
      

      jTraceEx:

      Exception: Thrown from class C
       at seabird.test.C.exc(index.php:78)
       at seabird.test.C.doexc(index.php:70)
       at seabird.test.fail2(index.php:85)
       at seabird.test.fail1(index.php:89)
       at (main)(index.php:93)
      Caused by: Exception: Thrown from class B
       at seabird.test.B.exc(index.php:64)
       at seabird.test.C.exc(index.php:75)
       ... 4 more
      Caused by: Exception: Thrown from class A
       at seabird.test.A.exc(index.php:46)
       at seabird.test.B.exc(index.php:61)
       ... 5 more
      

      【讨论】:

        【解决方案6】:

        您可以使用

        打印回溯
        debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
        

        它不会截断。

        示例打印将是

        #0  W3\\Sausage\\Mushroom->setCredentials() called at [/sausage/common/library/W3/Vzaar/Api.php:40]
        #1  W3\\Sausage\\Mushroom->__construct() called at [/sausage/common/modules/video.mod.php:24]
        #2  ModVideo->__construct() called at [/sausage/common/core/modules.core.php:133]
        #3  Modules->__get() called at [/sausage/common/search/Classified/ESAdapter.php:399]
        #4  Base\\Search\\Classified\\ESAdapter->getVideoInfo() called at [/sausage/common/search/Classified/ESAdapter.php:436]
        #5  Base\\Search\\Classified\\ESAdapter->fillDataSet() called at [/sausage/common/search/Adapter.php:58]
        

        【讨论】:

          【解决方案7】:

          在重新抛出异常的情况下,可以提供前一个异常作为第三个参数。通过这样做,可以链接异常跟踪。

          try  {
              f('123');
          } catch(Throwable $e){
              var_dump($e);
          }
          
          function f($arg){
              if(is_string($arg)){
                  try {
                      g($arg);
                  } catch(UnexpectedValueException $e) {
                      // Supply a third argument to pass the previous Exception.
                      throw new RuntimeException('Error in function g()', $e->getCode(), $e);
                  } catch(Throwable $e) {
                      // Supply a third argument to pass the previous Exception.
                      throw new RuntimeException('Unkown Error in function g()', $e->getCode(), $e);
                  }   
              }   
          }
          
          function g($string){
              if(strlen($string) < 6){
                  try {
                      h($string);
                  } catch(UnexpectedValueException $e) {
                      throw new UnexpectedValueException('String is smaller then 6', $e->getCode(), $e);
                  }
              }
              return $string;
          }
          
          function h($string){
              if(strlen($string) < 4){
                  throw new UnexpectedValueException('String is smaller then 4');
              }
              return $string;
          }
          

          输出:

          C:\wamp64\www\julian\index.php:21:
          object(RuntimeException)[3]
            protected 'message' => string 'Error in function g()' (length=21)
            private 'string' (Exception) => string '' (length=0)
            protected 'code' => int 0
            protected 'file' => string 'C:\wamp64\www\julian\index.php' (length=30)
            protected 'line' => int 30
            private 'trace' (Exception) => 
              array (size=1)
                0 => 
                  array (size=4)
                    'file' => string 'C:\wamp64\www\julian\index.php' (length=30)
                    'line' => int 19
                    'function' => string 'f' (length=1)
                    'args' => 
                      array (size=1)
                        0 => string '123' (length=3)
            private 'previous' (Exception) => 
              object(UnexpectedValueException)[2]
                protected 'message' => string 'String is smaller then 6' (length=24)
                private 'string' (Exception) => string '' (length=0)
                protected 'code' => int 0
                protected 'file' => string 'C:\wamp64\www\julian\index.php' (length=30)
                protected 'line' => int 43
                private 'trace' (Exception) => 
                  array (size=2)
                    0 => 
                      array (size=4)
                        'file' => string 'C:\wamp64\www\julian\index.php' (length=30)
                        'line' => int 27
                        'function' => string 'g' (length=1)
                        'args' => 
                          array (size=1)
                            0 => string '123' (length=3)
                    1 => 
                      array (size=4)
                        'file' => string 'C:\wamp64\www\julian\index.php' (length=30)
                        'line' => int 19
                        'function' => string 'f' (length=1)
                        'args' => 
                          array (size=1)
                            0 => string '123' (length=3)
                private 'previous' (Exception) => 
                  object(UnexpectedValueException)[1]
                    protected 'message' => string 'String is smaller then 4' (length=24)
                    private 'string' (Exception) => string '' (length=0)
                    protected 'code' => int 0
                    protected 'file' => string 'C:\wamp64\www\julian\index.php' (length=30)
                    protected 'line' => int 51
                    private 'trace' (Exception) => 
                      array (size=3)
                        0 => 
                          array (size=4)
                            'file' => string 'C:\wamp64\www\julian\index.php' (length=30)
                            'line' => int 41
                            'function' => string 'h' (length=1)
                            'args' => 
                              array (size=1)
                                0 => string '123' (length=3)
                        1 => 
                          array (size=4)
                            'file' => string 'C:\wamp64\www\julian\index.php' (length=30)
                            'line' => int 27
                            'function' => string 'g' (length=1)
                            'args' => 
                              array (size=1)
                                0 => string '123' (length=3)
                        2 => 
                          array (size=4)
                            'file' => string 'C:\wamp64\www\julian\index.php' (length=30)
                            'line' => int 19
                            'function' => string 'f' (length=1)
                            'args' => 
                              array (size=1)
                                0 => string '123' (length=3)
                    private 'previous' (Exception) => null
                    public 'xdebug_message' => string '<tr><th align='left' bgcolor='#f57900' colspan="5"><span style='background-color: #cc0000; color: #fce94f; font-size: x-large;'>( ! )</span> UnexpectedValueException: String is smaller then 4 in C:\wamp64\www\julian\index.php on line <i>51</i></th></tr>
          <tr><th align='left' bgcolor='#e9b96e' colspan='5'>Call Stack</th></tr>
          <tr><th align='center' bgcolor='#eeeeec'>#</th><th align='left' bgcolor='#eeeeec'>Time</th><th align='left' bgcolor='#eeeeec'>Memory</th><th align='left' bgcolor='#eeeeec'>Function</th><th align='left' bgcolor='#eeeeec'>Location</th></tr>
          <tr><td bgcolor='#eeeeec' align='center'>1</td><td bgcolor='#eeeeec' align='center'>0.0034</td><td bgcolor='#eeeeec' align='right'>361152</td><td bgcolor='#eeeeec'>{main}(  )</td><td title='C:\wamp64\www\julian\index.php' bgcolor='#eeeeec'>...\index.php<b>:</b>0</td></tr>
          <tr><td bgcolor='#eeeeec' align='center'>2</td><td bgcolor='#eeeeec' align='center'>0.0034</td><td bgcolor='#eeeeec' align='right'>361528</td><td bgcolor='#eeeeec'>f(  )</td><td title='C'... (length=1645)
                public 'xdebug_message' => string '<tr><th align='left' bgcolor='#f57900' colspan="5"><span style='background-color: #cc0000; color: #fce94f; font-size: x-large;'>( ! )</span> UnexpectedValueException: String is smaller then 6 in C:\wamp64\www\julian\index.php on line <i>43</i></th></tr>
          <tr><th align='left' bgcolor='#e9b96e' colspan='5'>Call Stack</th></tr>
          <tr><th align='center' bgcolor='#eeeeec'>#</th><th align='left' bgcolor='#eeeeec'>Time</th><th align='left' bgcolor='#eeeeec'>Memory</th><th align='left' bgcolor='#eeeeec'>Function</th><th align='left' bgcolor='#eeeeec'>Location</th></tr>
          <tr><td bgcolor='#eeeeec' align='center'>1</td><td bgcolor='#eeeeec' align='center'>0.0034</td><td bgcolor='#eeeeec' align='right'>361152</td><td bgcolor='#eeeeec'>{main}(  )</td><td title='C:\wamp64\www\julian\index.php' bgcolor='#eeeeec'>...\index.php<b>:</b>0</td></tr>
          <tr><td bgcolor='#eeeeec' align='center'>2</td><td bgcolor='#eeeeec' align='center'>0.0034</td><td bgcolor='#eeeeec' align='right'>361528</td><td bgcolor='#eeeeec'>f(  )</td><td title='C'... (length=1376)
            public 'xdebug_message' => string '<tr><th align='left' bgcolor='#f57900' colspan="5"><span style='background-color: #cc0000; color: #fce94f; font-size: x-large;'>( ! )</span> RuntimeException: Error in function g() in C:\wamp64\www\julian\index.php on line <i>30</i></th></tr>
          <tr><th align='left' bgcolor='#e9b96e' colspan='5'>Call Stack</th></tr>
          <tr><th align='center' bgcolor='#eeeeec'>#</th><th align='left' bgcolor='#eeeeec'>Time</th><th align='left' bgcolor='#eeeeec'>Memory</th><th align='left' bgcolor='#eeeeec'>Function</th><th align='left' bgcolor='#eeeeec'>Location</th></tr>
          <tr><td bgcolor='#eeeeec' align='center'>1</td><td bgcolor='#eeeeec' align='center'>0.0034</td><td bgcolor='#eeeeec' align='right'>361152</td><td bgcolor='#eeeeec'>{main}(  )</td><td title='C:\wamp64\www\julian\index.php' bgcolor='#eeeeec'>...\index.php<b>:</b>0</td></tr>
          <tr><td bgcolor='#eeeeec' align='center'>2</td><td bgcolor='#eeeeec' align='center'>0.0034</td><td bgcolor='#eeeeec' align='right'>361528</td><td bgcolor='#eeeeec'>f(  )</td><td title='C:\wamp64\ww'... (length=1096)
          

          【讨论】:

            【解决方案8】:

            我(最近,在我思考如何更好、尽可能准确和描述性地发出异常警告之后)通过以下(可能不完美,但仍然可用)方法解决了 getTrace 报告不完整的问题:

            private function Create_TraceText()
            {
                $trace_text = "<b>TRACE:</b> <br /><br />\n";
                $trace = $this -> getTrace();
            
                for($index = 0; $index < count($trace); $index++)
                {
                    $trace_text .= 'STEP ' . ($index + 1) . ":<br />\n";
            
                    foreach($trace[$index] as $trace_name => $trace_value)
                    {
                        $trace_value = $this -> Convert_StringifyEmpty($trace_value);
                        $trace_value = $this -> Convert_StringifyNull($trace_value);
                        $trace_value = $this -> Convert_StringifyArray($trace_value);
                        $trace_text .= strtoupper($trace_name == 'args' ? 'arguments' : $trace_name) . ': ' . $trace_value . "<br />\n";
                    }
            
                    $trace_text .= "<br />\n";
                }
            
                return $trace_text;
            }
            

            方法Create_TraceText 调用(也是)我自己的三个其他方法。这些方法有以下目的:

            • 在未设置参数的情况下插入替代文本
            • 用 NULL 字符串替换 NULL 值
            • 将参数的数组转换成字符串(用逗号作为胶水
            • 让代码更易读

            我选择了私有可访问性,因为它是由处理报告组装的方法在内部调用的。但是,如果您愿意,可以将其公开。

            它遍历跟踪,获取每个步骤的项目(键和它们的值)并将它们转换为下面写的形式的字符串

            TRACE:
            
            STEP 1:
            FILE: A:\WWW\Kilometrovnik\Kilometrovnik.php
            LINE: 166
            FUNCTION: Execute
            CLASS: VMaX\MarC\Assemblers\CodeGenerator
            TYPE: ->
            ARGUMENTS: not defined
            

            上面的例子只有一个步骤,但如果跟踪需要,它可以重复(自动完成)。


            注意:

            当然可以直接使用getTrace方法。我选择了当前的方式来支持使代码更具可读性(并且可能更快 - 如果方法 getTrace 仅使用一次)。

            此外,如果您愿意,您可以删除将 args 替换为 arguments(并已写入 args)或将跟踪项设为小写,默认情况下。

            跟踪部分类和函数可以合并为方法。但当然不是必须的。

            示例来自我的localhost私测项目(你的文件名可能不同)。

            【讨论】:

              【解决方案9】:

              如果您可以摆脱var_dump(),一个简单的解决方案是:

              try {
                 ...
              } catch (Exception $e)
                 var_dump($e->getTrace());
              }
              

              从这个伟大的answer by Andre偷来的

              【讨论】:

              • 这只会输出一个数组
              猜你喜欢
              • 1970-01-01
              • 2012-05-22
              • 1970-01-01
              • 2011-02-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-11-09
              • 1970-01-01
              相关资源
              最近更新 更多