getMessage() . " on file '". $e->getFile() . "' at line {$e->getLine()}"; $anom_ERRORS[] = $message; // store the error } /** * Catch fatal error work-around * (set_error_handler not working on fatal errors). */ function on_shutdown_check_for_fatal() { global $anom_ERRORS; $error = error_get_last(); if ($error != null) { // ignore 'normal' system shutdowns [exit|die]() if ( $error["type"] == E_ERROR ) { // get as much error-info handle_error( $error["type"] ?? -1, $error["message"] ?? 'unknown error', $error["file"] ?? 'unknown file', $error["line"] ?? -1 ); } } if (($anom_ERRORS != [])) { // TODO: // Implemetnig the design/layout of the error-messages // output should not be an error's-handling task, thus // shall be assigned to the Rendes/View level; // Same about the log service channels // TODO: // FORWARD ERRORS into LOG-SYSTEM // ex. into some file... // file_put_contents("logs/thowable.log", $message_template .PHP_EOL, FILE_APPEND); // or ...some other channer (Email, Slack, Database etc). // Channes can be decided according to error severity; // a file-system error loggin for backup is recommended // partitioniong of errors onto file-system can be useful // TODO: // 1st: Log Errors // 2nd: Show Errors if (PRODUCTION) { if (!defined('VIEW_LOADED')) { // throw a prety-error message render_view('error/general', ['message' => 'Please forgive me, I know not what I do']); } } else { if (!defined('VIEW_LOADED')) { // no template loaded; render erros in general-error template render_view('error/general', ['message' => implode("
And:
", $anom_ERRORS)]); } else { echo '
Errors:
'. implode("
And:
", $anom_ERRORS) .'
'; } } } } // register callback on shutdown register_shutdown_function( "on_shutdown_check_for_fatal" ); // register custom error handler callback set_error_handler( "handle_error" ); // set custom exception handler function set_exception_handler( "handle_exception" ); // send errors to stderr (instead of stdout) ini_set( "display_errors", "off" ); // thow out all errors error_reporting( E_ALL );