如何让 PHP 在出现错误时产生回溯?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1159216/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I get PHP to produce a backtrace upon errors?
提问by chaos
Trying to debug PHP using its default current-line-only error messages is horrible. How can I get PHP to produce a backtrace (stack trace) when errors are produced?
尝试使用其默认的仅当前行错误消息来调试 PHP 是可怕的。发生错误时,如何让 PHP 生成回溯(堆栈跟踪)?
采纳答案by patcoll
回答by chaos
My script for installing an error handler that produces a backtrace:
我用于安装产生回溯的错误处理程序的脚本:
<?php
function process_error_backtrace($errno, $errstr, $errfile, $errline, $errcontext) {
if(!(error_reporting() & $errno))
return;
switch($errno) {
case E_WARNING :
case E_USER_WARNING :
case E_STRICT :
case E_NOTICE :
case E_USER_NOTICE :
$type = 'warning';
$fatal = false;
break;
default :
$type = 'fatal error';
$fatal = true;
break;
}
$trace = array_reverse(debug_backtrace());
array_pop($trace);
if(php_sapi_name() == 'cli') {
echo 'Backtrace from ' . $type . ' \'' . $errstr . '\' at ' . $errfile . ' ' . $errline . ':' . "\n";
foreach($trace as $item)
echo ' ' . (isset($item['file']) ? $item['file'] : '<unknown file>') . ' ' . (isset($item['line']) ? $item['line'] : '<unknown line>') . ' calling ' . $item['function'] . '()' . "\n";
} else {
echo '<p class="error_backtrace">' . "\n";
echo ' Backtrace from ' . $type . ' \'' . $errstr . '\' at ' . $errfile . ' ' . $errline . ':' . "\n";
echo ' <ol>' . "\n";
foreach($trace as $item)
echo ' <li>' . (isset($item['file']) ? $item['file'] : '<unknown file>') . ' ' . (isset($item['line']) ? $item['line'] : '<unknown line>') . ' calling ' . $item['function'] . '()</li>' . "\n";
echo ' </ol>' . "\n";
echo '</p>' . "\n";
}
if(ini_get('log_errors')) {
$items = array();
foreach($trace as $item)
$items[] = (isset($item['file']) ? $item['file'] : '<unknown file>') . ' ' . (isset($item['line']) ? $item['line'] : '<unknown line>') . ' calling ' . $item['function'] . '()';
$message = 'Backtrace from ' . $type . ' \'' . $errstr . '\' at ' . $errfile . ' ' . $errline . ': ' . join(' | ', $items);
error_log($message);
}
if($fatal)
exit(1);
}
set_error_handler('process_error_backtrace');
?>
Caveat: it is powerless to affect various 'PHP Fatal Errors', since Zend in their wisdom decided that these would ignore set_error_handler(). So you still get useless final-location-only errors with those.
警告:无法影响各种“PHP 致命错误”,因为 Zend 以他们的智慧决定这些将忽略set_error_handler(). 所以你仍然会遇到无用的最终位置错误。
回答by kenorb
PHP Error
PHP错误
This is better error reporting for PHP written in PHP. No extra extensions are required!
对于用 PHP 编写的 PHP,这是更好的错误报告。不需要额外的扩展!
It is trivial to use where all errors are displayed in the browser for normal, AJAXy requests (in paused state). Then all errors provides you with a backtrace and code context across the whole stack trace, including function arguments, server variables.
对于正常的 AJAXy 请求(处于暂停状态),在浏览器中显示所有错误的地方使用它是微不足道的。然后,所有错误都会为您提供整个堆栈跟踪中的回溯和代码上下文,包括函数参数、服务器变量。
All you need to do is to include one single file and call the function (at the beginning on your code), e.g.
您需要做的就是包含一个文件并调用该函数(在代码的开头),例如
require('php_error.php');
\php_error\reportErrors();
See the screenshots:
看截图:
GitHub: https://github.com/JosephLenton/PHP-Error
GitHub: https://github.com/JosephLenton/PHP-Error
My fork (with extra fixes): https://github.com/kenorb-contrib/PHP-Error
我的叉子(有额外的修复):https: //github.com/kenorb-contrib/PHP-Error
Debug PHPclass
调试 PHP类
A complete PHP debugger class, with support for Exception, Errors, Alerts ( from user), code lines and highlight flags.
一个完整的 PHP 调试器类,支持异常、错误、警报(来自用户)、代码行和高亮标志。
Example usage:
用法示例:
<?php
include( dirname(dirname(__FILE__)) . '/src/Debug.php' );
//Catch all
Debug::register();
//Generate an errors
if( this_function_does_not_exists( ) )
{
return false;
}
?>
Error Handling in PHP
PHP 中的错误处理
The example below shows the handling of internal exceptions by triggering errors and handling them with a user defined function:
下面的示例显示了通过触发错误并使用用户定义的函数处理它们来处理内部异常:
Shorter way (PHP):
更短的方式(PHP):
<?php
function e($number, $msg, $file, $line, $vars) {
print_r(debug_backtrace());
die();
}
set_error_handler('e');
Longer way (PHP):
更长的路(PHP):
// set to the user defined error handler
$old_error_handler = set_error_handler("myErrorHandler");
// error handler function
function myErrorHandler($errno, $errstr, $errfile, $errline)
{
if (!(error_reporting() & $errno)) {
// This error code is not included in error_reporting
return;
}
switch ($errno) {
case E_USER_ERROR:
echo "<b>My ERROR</b> [$errno] $errstr<br />\n";
echo " Fatal error on line $errline in file $errfile";
echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />\n";
echo "Aborting...<br />\n";
var_dump(debug_backtrace());
exit(1);
break;
case E_USER_WARNING:
echo "<b>My WARNING</b> [$errno] $errstr<br />\n";
break;
case E_USER_NOTICE:
echo "<b>My NOTICE</b> [$errno] $errstr<br />\n";
break;
default:
echo "Unknown error type: [$errno] $errstr<br />\n";
break;
}
/* Don't execute PHP internal error handler */
return true;
}
See: http://www.php.net/manual/en/function.set-error-handler.php
请参阅:http: //www.php.net/manual/en/function.set-error-handler.php
Note: You can only have one error exception at a time. When you call the set_error_handler() function it will return the name of the old error handler. You can store this and call it yourself from your error handler – thus allowing you to have multiple error handlers.
注意:一次只能有一个错误异常。当您调用 set_error_handler() 函数时,它将返回旧错误处理程序的名称。您可以存储它并从您的错误处理程序中自己调用它——从而允许您拥有多个错误处理程序。
XDebug
调试
For more advanced solution, you can use XDebugextension for PHP.
对于更高级的解决方案,您可以使用PHP 的XDebug扩展。
By default when XDebug is loaded, it should show you automatically the backtrace in case of any fatal error. Or you trace into file (xdebug.auto_trace) to have a very big backtrace of the whole request or do the profiling (xdebug.profiler_enable) or other settings. If the trace file is too big, you can use xdebug_start_trace() and xdebug_stop_trace() to dump the partial trace.
默认情况下,当 XDebug 被加载时,它应该自动向你显示任何致命错误的回溯。或者您跟踪文件 (xdebug.auto_trace) 以对整个请求进行非常大的回溯,或者进行分析 (xdebug.profiler_enable) 或其他设置。如果跟踪文件太大,您可以使用 xdebug_start_trace() 和 xdebug_stop_trace() 转储部分跟踪。
Installation
安装
Using PECL:
使用 PECL:
pecl install xdebug
On Linux:
在 Linux 上:
sudo apt-get install php5-xdebug
On Mac (with Homebrew):
在 Mac 上(使用 Homebrew):
brew tap josegonzalez/php
brew search xdebug
php53-xdebug
Example of mine configuration:
我的配置示例:
[xdebug]
; Extensions
extension=xdebug.so
; zend_extension="/YOUR_PATH/php/extensions/no-debug-non-zts-20090626/xdebug.so"
; zend_extension="/Applications/MAMP/bin/php/php5.3.20/lib/php/extensions/no-debug-non-zts-20090626/xdebug.so" ; MAMP
; Data
xdebug.show_exception_trace=1 ; bool: Show a stack trace whenever an exception is raised.
xdebug.collect_vars = 1 ; bool: Gather information about which variables are used in a certain scope.
xdebug.show_local_vars=1 ; int: Generate stack dumps in error situations.
xdebug.collect_assignments=1 ; bool: Controls whether Xdebug should add variable assignments to function traces.
xdebug.collect_params=4 ; int1-4: Collect the parameters passed to functions when a function call is recorded.
xdebug.collect_return=1 ; bool: Write the return value of function calls to the trace files.
xdebug.var_display_max_children=256 ; int: Amount of array children and object's properties are shown.
xdebug.var_display_max_data=1024 ; int: Max string length that is shown when variables are displayed.
xdebug.var_display_max_depth=3 ; int: How many nested levels of array/object elements are displayed.
xdebug.show_mem_delta=0 ; int: Show the difference in memory usage between function calls.
; Trace
xdebug.auto_trace=0 ; bool: The tracing of function calls will be enabled just before the script is run.
xdebug.trace_output_dir="/var/log/xdebug" ; string: Directory where the tracing files will be written to.
xdebug.trace_output_name="%H%R-%s-%t" ; string: Name of the file that is used to dump traces into.
; Profiler
xdebug.profiler_enable=0 ; bool: Profiler which creates files read by KCacheGrind.
xdebug.profiler_output_dir="/var/log/xdebug" ; string: Directory where the profiler output will be written to.
xdebug.profiler_output_name="%H%R-%s-%t" ; string: Name of the file that is used to dump traces into.
xdebug.profiler_append=0 ; bool: Files will not be overwritten when a new request would map to the same file.
; CLI
xdebug.cli_color=1 ; bool: Color var_dumps and stack traces output when in CLI mode.
; Remote debugging
xdebug.remote_enable=off ; bool: Try to contact a debug client which is listening on the host and port.
xdebug.remote_autostart=off ; bool: Start a remote debugging session even GET/POST/COOKIE variable is not present.
xdebug.remote_handler=dbgp ; select: php3/gdb/dbgp: The DBGp protocol is the only supported protocol.
xdebug.remote_host=localhost ; string: Host/ip where the debug client is running.
xdebug.remote_port=9000 ; integer: The port to which Xdebug tries to connect on the remote host.
xdebug.remote_mode=req ; select(req,jit): Selects when a debug connection is initiated.
xdebug.idekey="xdebug-cli" ; string: IDE Key Xdebug which should pass on to the DBGp debugger handler.
xdebug.remote_log="/var/log/xdebug.log" ; string: Filename to a file to which all remote debugger communications are logged.
Drupal 6&7
Drupal 6&7
With Devel enabled:
启用开发:
/**
* Implements hook_watchdog().
*/
function foo_watchdog($log_entry) {
if ($log_entry['type'] == 'php' && $log_entry['severity'] <= WATCHDOG_WARNING) {
function_exists('dd') && dd(debug_backtrace());
}
}
Above function will log the backtraces on each error into temporary file (/tmp/drupal_debug.txtby default).
上面的函数会将每个错误的回溯记录到临时文件中(/tmp/drupal_debug.txt默认情况下)。
Or locate the file via: drush eval "echo file_directory_temp() . '/drupal_debug.txt'.
或通过以下方式定位文件:drush eval "echo file_directory_temp() . '/drupal_debug.txt'。
Without Devel enabled, use old school approach: var_dump(debug_backtrace());instead of dd().
在没有启用 Devel 的情况下,使用老派方法:var_dump(debug_backtrace());而不是dd().
回答by Tim
I just tried setting a session variable containing the contents of debug_backtrace() at the offending line, then printing it using register_shutdown_function(). Worked like a charm.
我只是尝试在违规行设置一个包含 debug_backtrace() 内容的会话变量,然后使用 register_shutdown_function() 打印它。像魅力一样工作。
回答by Mythica
You can use debug_backtrace
您可以使用debug_backtrace
回答by GetFree
This is how you do it:
这是你如何做到的:
set_error_handler(function($errorType){
if(error_reporting() & $errorType){
?><pre><?
debug_print_backtrace();
?></pre><?
}
}) ;
It requires PHP 5.3+ since it uses a closure. If you need lower PHP support just convert the closure to a normal function.
它需要 PHP 5.3+,因为它使用了闭包。如果您需要较低的 PHP 支持,只需将闭包转换为普通函数即可。
回答by T0xicCode
回答by Lukasz Czerwinski
set_error_handler()+ debug_backtrace()+ debug_print_backtrace()in PHP5
set_error_handler()+ debug_backtrace()+debug_print_backtrace()在PHP5
回答by smoove
$backtrace = debug_backtrace();
i wrote a little article about backtracinga while back
回答by Beto Aveiga
If you can't install a debugger then use this function sorrounding the fatal error to get the "fatal stack". Check the code and example below that explains better how to use it:
如果您无法安装调试器,请使用此功能解决致命错误以获取“致命堆栈”。检查下面的代码和示例,它更好地解释了如何使用它:
// Give an extra parameter to the filename
// to save multiple log files
function _fatalog_($extra = false)
{
static $last_extra;
// CHANGE THIS TO: A writeable filepath in your system...
$filepath = '/var/www/html/sites/default/files/fatal-'.($extra === false ? $last_extra : $extra).'.log';
if ($extra===false) {
unlink($filepath);
} else {
// we write a log file with the debug info
file_put_contents($filepath, json_encode(debug_backtrace()));
// saving last extra parameter for future unlink... if possible...
$last_extra = $extra;
}
}
Here's an example of how to use it:
以下是如何使用它的示例:
// A function which will produce a fatal error
function fatal_example()
{
_fatalog_(time()); // writing the log
$some_fatal_code = array()/3; // fatality!
_fatalog_(); // if we get here then delete last file log
}
Finally to read the contents of the log...
终于要读取日志的内容了...
var_dump(json_decode(file_get_contents('/path/to-the-fatal.log')));
Hope that helps!
希望有帮助!


