Actually, I do have another piece of code which I am proud of... It's an error handling class which I use in an in-house framework. It allows to trigger errors within classes and return the calling line versus the line where the error has been triggered. It also allows to log the error to the display/email/logfile depending of the server type (Production or Dev). Completely replaces the crappy PHP error handler on anything other than syntax errors.
define('HANDLER_NORMAL', 0);
define('HANDLER_EXIT_FUNCTION', 1);
define('HANDLER_EXIT_CLASS', 2);
require_once ABSPATH . "includes/framework/functions/SiteLog.php";
class ErrorHandler {
public static $DBfatal = true;
public static $DBsilent = false;
public static function custom_error_handler($code, $message, $type = 0) {
ErrorHandler::handle($code, $message, ErrorHandler::get_backtrace($type));
}
public static function php_error_handler($code, $message) {
ErrorHandler::handle($code, $message, ErrorHandler::get_backtrace(0));
}
public static function pear_error_handler($err) {
if (@is_a($err, 'MDB2_Error')) {
if(!ErrorHandler::$DBsilent) {
$level = (ErrorHandler::$DBfatal) ? E_USER_ERROR : E_USER_WARNING;
if ($err->userinfo) {
ErrorHandler::log(PEAR_LOG_NOTICE, trim(str_replace(array
(
"\n",
"\r"
), array
(
' ',
''
), $err->userinfo)));
}
ErrorHandler::handle($level, $err->message, ErrorHandler::get_backtrace(HANDLER_EXIT_CLASS));
}
} else ErrorHandler::handle($err->level, $err->message, ErrorHandler::get_backtrace(HANDLER_EXIT_CLASS));
}
private static function get_backtrace($type = 0) {
$regEx = "/^" . preg_quote(ABSPATH, '/') . '/' . ((server_is_windows()) ? 'i' : '');
$tmp = debug_backtrace();
$backtrace = array();
for ($i = 0; $i < count($tmp); $i++) {
unset($tmp[$i]['object']);
if ($tmp[$i]['file']) {
$tmp[$i]['file'] = str_replace('\\', '/', $tmp[$i]['file']);
if (preg_match($regEx, $tmp[$i]['file'])) {
$tmp[$i]['file'] = preg_replace($regEx, '', $tmp[$i]['file']);
}
}
if (count($backtrace) == 0) {
$isMyHandler = ($tmp[$i]['file'] == 'includes/framework/functions/ErrorHandler.php' || $tmp[$i]['class'] == 'ErrorHandler' || $tmp[$i]['function'] == 'trigger_php_error');
$isPearError = (!is_null($tmp[$i]['class']) && ($tmp[$i]['class'] == 'PEAR_Error' || is_subclass_of($tmp[$i]['class'], 'PEAR_Error')));
$isCallback = ($tmp[$i]['function'] == 'call_user_func' && (is_array($tmp[$i]['args'][0]) && $tmp[$i]['args'][0][0] == 'ErrorHandler'));
$isSomeHandler = (!is_null($tmp[$i]['function']) && stripos($tmp[$i]['function'], 'error') !== FALSE);
$isLast = ($i == (count($tmp) - 1));
if(!($isMyHandler || $isPearError || $isCallback || $isSomeHandler) || $isLast) {
$backtrace[] = $tmp[$i];
}
} else {
$backtrace[] = $tmp[$i];
}
}
switch ($type)
{
case HANDLER_EXIT_FUNCTION:
array_shift($backtrace);
break;
case HANDLER_EXIT_CLASS:
$orgClass = $backtrace[0]['class'];
if(!is_null($orgClass)) {
while (count($backtrace) > 1 && $backtrace[1]['class'] == $orgClass) {
array_shift($backtrace);
}
}
break;
}
return $backtrace;
}
private static function handle($code, $message, $backtrace) {
$logPriority = PEAR_LOG_INFO;
switch ($code)
{
case E_ERROR:
case E_USER_ERROR:
if ((error_reporting() & E_ERROR) == 0) exit(1);
$logPriority = PEAR_LOG_ERR;
break;
case E_WARNING:
case E_USER_WARNING:
if ((error_reporting() & E_WARNING) == 0) return;
$logPriority = PEAR_LOG_WARNING;
break;
case E_USER_NOTICE:
if ((error_reporting() & E_NOTICE) == 0) return;
$logPriority = PEAR_LOG_NOTICE;
break;
default:
return;
break;
}
$message = strip_tags($message);
$logText = $message . ' in ' . $backtrace[0]['file'] . ' at line ' . $backtrace[0]['line'];
ErrorHandler::log($logPriority, $logText);
ErrorHandler::write_dump($code, $message, $backtrace);
if ($code == E_USER_ERROR || $code == E_ERROR) exit(1);
}
private static function log($priority, $message) {
$logger = &SiteLog::get('php_sapi', true, SERVERTYPE == 'PROD');
$logger->log($message, $priority);
}
private static function write_dump($code, $message, $backtrace) {
global $argv;
$filename = date('YmdHis');
$codeName = 'Unknown';
switch ($code)
{
case E_ERROR:
case E_USER_ERROR:
$codeName = 'Error';
break;
case E_WARNING:
case E_USER_WARNING:
$codeName = 'Warning';
break;
case E_NOTICE:
case E_USER_NOTICE:
$codeName = 'Notice';
break;
default:
break;
}
$loginfo['type'] = $codeName;
$loginfo['msg'] = $message;
$loginfo['cli'] = ISCLI;
if ($loginfo['cli']) {
$loginfo['argv'] = $argv;
}
else {
$loginfo['request'] = @substr($_SERVER['REQUEST_URI'], strlen(RELADDR));
$loginfo['get'] = $_GET;
$loginfo['post'] = $_POST;
}
$loginfo['backtrace'] = $backtrace;
$logstr = Spyc::YAMLDump($loginfo, false, 0);
file_put_contents(sprintf("%sautomation/logs/error_dumps/%s_%s.log", ABSPATH, $filename, sha1($logstr)), $logstr);
}
}
function trigger_php_error($message, $level, $mode = 0) {
ErrorHandler::custom_error_handler($level, $message, $mode);
}
ini_set('track_errors', 1);
set_error_handler(array('ErrorHandler', 'php_error_handler'));
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array('ErrorHandler', 'pear_error_handler'));