I have created this code for user error logging, and I am wondering if there is anything that can be improved. The point is that this error handler would ONLY catch user errors created in-code by trigger_error(), and would display, log, and/or email the error, depending on the config settings. The error logging class is loaded by an autoloader function. For production, all error levels would be set to 0, and the user error handler would never be set, and the class would never be loaded.Config file: // user error display level (change for production) define('LEV_USER_ERROR_DISPLAY_LEVEL', E_USER_ERROR); // user error logging level (change for production) define('LEV_USER_ERROR_LOG_LEVEL', E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE); // user error email alert level define('LEV_USER_ERROR_EMAIL_LEVEL', 0); // user error email address list (e.g. 'someone1@somewhere.com, someone2@somewhere.com') define('LEV_USER_ERROR_EMAIL_ADDRESSES', '');Init file:   // set user error handler   if (LEV_USER_ERROR_LOG_LEVEL | LEV_USER_ERROR_DISPLAY_LEVEL | LEV_USER_ERROR_EMAIL_LEVEL) {    set_error_handler('lev_user_error_handler::user_error_handler', LEV_USER_ERROR_LOG_LEVEL | LEV_USER_ERROR_DISPLAY_LEVEL | LEV_USER_ERROR_EMAIL_LEVEL);   }Error logging class file:<?php // user error handler class lev_user_error_handler {  // user error handler  public static function user_error_handler($error_level, $message, $file_name, $line_number) {   if ((LEV_USER_ERROR_LOG_LEVEL | LEV_USER_ERROR_DISPLAY_LEVEL) == 0) return true;   switch ($error_level) {    case E_USER_ERROR:     if (LEV_USER_ERROR_DISPLAY_LEVEL & E_USER_ERROR) {      echo '[' . date('Y-m-d h:i:s') . '] User Level Error: ' . $message . ', File: '.$file_name.', Line: '.$line_number.'<br />';     }     if (LEV_USER_ERROR_LOG_LEVEL & E_USER_ERROR) {      error_log('[' . date('Y-m-d h:i:s') . '] User Error: ' . $message . ', File: '.$file_name.', Line: '.$line_number.', Request: ' . $_SERVER['ORIG_PATH_INFO'] . \\n, 3, 'application/logs/user_error_log.txt');     }     if (LEV_USER_ERROR_EMAIL_LEVEL & E_USER_ERROR) {      error_log('[' . date('Y-m-d h:i:s') . '] User Error: ' . $message . ', File: '.$file_name.', Line: '.$line_number.', Request: ' . $_SERVER['ORIG_PATH_INFO'] . '', 1, LEV_USER_ERROR_EMAIL_ADDRESSES, 'From: no-reply@' . preg_replace('/^.+?\./i', '', $_SERVER['SERVER_NAME']));     }     die;     break;    case E_USER_WARNING:     if (LEV_USER_ERROR_DISPLAY_LEVEL & E_USER_WARNING) {      echo '[' . date('Y-m-d h:i:s') . '] User Level Warning: ' . $message . ', File: '.$file_name.', Line: '.$line_number.'<br />';     }     if (LEV_USER_ERROR_LOG_LEVEL & E_USER_WARNING) {      error_log('[' . date('Y-m-d h:i:s') . '] User Warning: ' . $message . ', File: '.$file_name.', Line: '.$line_number.', Request: ' . $_SERVER['ORIG_PATH_INFO'] . \\n, 3, 'application/logs/user_error_log.txt');     }     if (LEV_USER_ERROR_EMAIL_LEVEL & E_USER_WARNING) {      error_log('[' . date('Y-m-d h:i:s') . '] User Error: ' . $message . ', File: '.$file_name.', Line: '.$line_number.', Request: ' . $_SERVER['ORIG_PATH_INFO'] . '', 1, LEV_USER_ERROR_EMAIL_ADDRESSES, 'From: no-reply@' . preg_replace('/^.+?\./i', '', $_SERVER['SERVER_NAME']));     }     break;    case E_USER_NOTICE:     if (LEV_USER_ERROR_DISPLAY_LEVEL & E_USER_NOTICE) {      echo '[' . date('Y-m-d h:i:s') . '] User Level Notice: ' . $message . ', File: '.$file_name.', Line: '.$line_number.'<br />';     }     if (LEV_USER_ERROR_LOG_LEVEL & E_USER_NOTICE) {      error_log('[' . date('Y-m-d h:i:s') . '] User Notice: ' . $message . ', File: '.$file_name.', Line: '.$line_number.', Request: ' . $_SERVER['ORIG_PATH_INFO'] . \\n, 3, 'application/logs/user_error_log.txt');     }     if (LEV_USER_ERROR_EMAIL_LEVEL & E_USER_NOTICE) {      error_log('[' . date('Y-m-d h:i:s') . '] User Error: ' . $message . ', File: '.$file_name.', Line: '.$line_number.', Request: ' . $_SERVER['ORIG_PATH_INFO'] . '', 1, LEV_USER_ERROR_EMAIL_ADDRESSES, 'From: no-reply@' . preg_replace('/^.+?\./i', '', $_SERVER['SERVER_NAME']));     }     break;    default:     // call PHP internal error handler     return false;   }   // do not call PHP internal error handler   return true;  } }?>
User error logging
php;error handling;php5
Personally I think that working with 50% native and 50% your code does not work very well, because of things such as trigger_error does not allow custom bits to be sent.That being said if you named your class Error and created it to be abstract that implements a logger interface (optional) you would be able to do more with it.Creating custom constants such as LOG,SHOW_ERROR,SEND_MAIL combined with a custom static function would be a better option, as doing things such as:Error::Trigger(Cannot divide by 0, Error::LOG | Error::SHOW_ERROR);makes more sense to have specific control over errors.Here's a small example how I would improve the aboveabstract class Error{    public const LOG = 0;    public const SEND_MAIL = 1;    public const SHOW_ERROR = 2;    /*...*/    public static function Monitor(){}; /*Used for set_error_handler*/    public static function Trigger($Message,$bits = Error::LOG | Error::SEND_MAIL,$Context = false)    {        if($bits & Error:LOG)        {             //Log it        }        if($bits & Error:SEND_MAIL)        {             //Send it        }        /*Lastly*/        if($bits & Error:LOG)        {             //Show it        }    }}you would then bind the Monitor to the error_reportng and call the Error::Trigger depending on what type of error has been triggered, or you could extend the class and run the parent static methodclass ErrorHandler extends Error{    public fucntion Monitor(/*...*/)    {        parent::Trigger(/*...*/);    }}And allow your class to handle all errors as you then have more control over the decision on what to do.you can then set the default error handling to a combination of options such as: define(DEFAULT_ERROR_HANDLING,Error:log | Error::SEND_MAIL);and change $bits in the parameter section of trigger to $bits = DEFAULT_ERROR_HANDLING