如何获取 PHP 的 getTraceAsString() 的完整字符串?
Posted
技术标签:
【中文标题】如何获取 PHP 的 getTraceAsString() 的完整字符串?【英文标题】:How can I get the full string of PHP’s 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...')
如何打印完整的字符串?
【问题讨论】:
嗨。很久很久以前,你在这里得到了一些很好的帮助。您介意接受答案,甚至发布您自己的答案吗?谢谢。 【参考方案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: file
和 Notice: 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://***.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
调用(也是)我自己的三个其他方法。这些方法有以下目的:
我选择了私有可访问性,因为它是由处理报告组装的方法在内部调用的。但是,如果您愿意,可以将其公开。
它遍历跟踪,获取每个步骤的项目(键和它们的值)并将它们转换为下面写的形式的字符串
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偷来的
【讨论】:
这只会输出一个数组以上是关于如何获取 PHP 的 getTraceAsString() 的完整字符串?的主要内容,如果未能解决你的问题,请参考以下文章