E_USER_WARNING, E_USER_NOTICE, and any other non-terminating error codes, are useless and act like E_USER_ERROR (which terminate) when you combine a custom ERROR_HANDLER with ErrorException and do not CATCH the error. There is NO way to return execution to the parent scope in the EXCEPTION_HANDLER.
<?php
error_reporting(E_ALL);
define('DEBUG', true);
define('LINEBREAK', "\r\n");
error::initiate('./error_backtrace.log');
try
trigger_error("First error", E_USER_NOTICE);
catch ( ErrorException $e )
print("Caught the error: ".$e->getMessage."<br />\r\n" );
trigger_error("This event WILL fire", E_USER_NOTICE);
trigger_error("This event will NOT fire", E_USER_NOTICE);
abstract class error {
public static $LIST = array();
private function __construct() {}
public static function initiate( $log = false ) {
set_error_handler( 'error::err_handler' );
set_exception_handler( 'error::exc_handler' );
if ( $log !== false ) {
if ( ! ini_get('log_errors') )
ini_set('log_errors', true);
if ( ! ini_get('error_log') )
ini_set('error_log', $log);
}
}
public static function err_handler($errno, $errstr, $errfile, $errline, $errcontext) {
$l = error_reporting();
if ( $l & $errno ) {
$exit = false;
switch ( $errno ) {
case E_USER_ERROR:
$type = 'Fatal Error';
$exit = true;
break;
case E_USER_WARNING:
case E_WARNING:
$type = 'Warning';
break;
case E_USER_NOTICE:
case E_NOTICE:
case @E_STRICT:
$type = 'Notice';
break;
case @E_RECOVERABLE_ERROR:
$type = 'Catchable';
break;
default:
$type = 'Unknown Error';
$exit = true;
break;
}
$exception = new \ErrorException($type.': '.$errstr, 0, $errno, $errfile, $errline);
if ( $exit ) {
exc_handler($exception);
exit();
}
else
throw $exception;
}
return false;
}
function exc_handler($exception) {
$log = $exception->getMessage() . "\n" . $exception->getTraceAsString() . LINEBREAK;
if ( ini_get('log_errors') )
error_log($log, 0);
print("Unhandled Exception" . (DEBUG ? " - $log" : ''));
}
}
?>