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 . ':' . "
";
foreach($trace as $item)
echo ' ' . (isset($item['file']) ? $item['file'] : '<unknown file>') . ' ' . (isset($item['line']) ? $item['line'] : '<unknown line>') . ' calling ' . $item['function'] . '()' . "
";
} else {
echo '<p class="error_backtrace">' . "
";
echo ' Backtrace from ' . $type . ' '' . $errstr . '' at ' . $errfile . ' ' . $errline . ':' . "
";
echo ' <ol>' . "
";
foreach($trace as $item)
echo ' <li>' . (isset($item['file']) ? $item['file'] : '<unknown file>') . ' ' . (isset($item['line']) ? $item['line'] : '<unknown line>') . ' calling ' . $item['function'] . '()</li>' . "
";
echo ' </ol>' . "
";
echo '</p>' . "
";
}
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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…