'Error', E_WARNING => 'Warning', E_PARSE => 'Parse Error', E_NOTICE => 'Notice', E_CORE_ERROR => 'Core Error', E_CORE_WARNING => 'Core Warning', E_COMPILE_ERROR => 'Compile Error', E_COMPILE_WARNING => 'Compile Warning', E_USER_ERROR => 'User Error', E_USER_WARNING => 'User Warning', E_USER_NOTICE => 'User Notice', E_STRICT => 'Strict Notice', E_RECOVERABLE_ERROR => 'Recoverable Error', E_DEPRECATED => 'Deprecated', E_USER_DEPRECATED => 'User Deprecated' ]; $errorType = $errorLevels[$errno] ?? 'Unknown Error'; $error = [ 'type' => 'php_error', 'level' => $errno, 'error_type' => $errorType, 'message' => $errstr, 'file' => $errfile, 'line' => $errline, 'context' => isset($errcontext['this']) ? get_class($errcontext['this']) : 'global', 'timestamp' => date('Y-m-d H:i:s'), 'request_uri' => $_SERVER['REQUEST_URI'] ?? '', 'remote_ip' => Security::getClientIP(), 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '', 'session_id' => session_id(), 'backtrace' => self::getBacktrace() ]; // Log the error self::logError($error); // In development, show errors if (Config::isEnvironment('development')) { // Return error info for debugging without exposing sensitive data return [ 'error' => true, 'type' => $errorType, 'message' => $errstr, 'file' => basename($errfile), 'line' => $errline ]; } // In production, don't show errors if (Config::isEnvironment('production')) { return false; // Let PHP handle it } // For PHP's error handling, still need to return false for some errors return ($errno & (E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR)) ? false : true; } /** * Uncaught exception handler */ public static function exceptionHandler($exception) { $error = [ 'type' => 'uncaught_exception', 'class' => get_class($exception), 'message' => $exception->getMessage(), 'code' => $exception->getCode(), 'file' => $exception->getFile(), 'line' => $exception->getLine(), 'timestamp' => date('Y-m-d H:i:s'), 'request_uri' => $_SERVER['REQUEST_URI'] ?? '', 'remote_ip' => Security::getClientIP(), 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '', 'session_id' => session_id(), 'backtrace' => self::getBacktrace(), 'previous' => $exception->getPrevious() ? $exception->getPrevious()->getMessage() : null ]; // Log the exception self::logError($error); // Handle display based on environment if (Config::isEnvironment('development')) { // Show detailed error page self::renderErrorPage($error, 500); exit; } else { // Show generic error page in production self::renderErrorPage([ 'message' => 'An unexpected error occurred. Please try again later.' ], 500); exit; } } /** * Shutdown handler for fatal errors */ public static function shutdownHandler() { $error = error_get_last(); if ($error !== null) { $fatalErrors = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR]; if (in_array($error['type'], $fatalErrors)) { $error['type'] = 'fatal_error'; $error['timestamp'] = date('Y-m-d H:i:s'); $error['request_uri'] = $_SERVER['REQUEST_URI'] ?? ''; $error['remote_ip'] = Security::getClientIP(); $error['user_agent'] = $_SERVER['HTTP_USER_AGENT'] ?? ''; $error['session_id'] = session_id(); $error['backtrace'] = self::getBacktrace(); self::logError($error); if (Config::isEnvironment('development')) { echo "

Fatal Error

"; echo "
" . htmlspecialchars(print_r($error, true)) . "
"; } else { self::renderErrorPage([ 'message' => 'A critical error occurred. Our team has been notified.' ], 500); } } } // Clean up tasks (optional) self::performCleanup(); } /** * Log error to file and/or external service */ private static function logError($error) { $logMessage = sprintf( "[%s] %s: %s in %s:%d\nContext: %s\nIP: %s\nURI: %s\nBacktrace:\n%s\n---\n", $error['timestamp'], $error['type'] ?? 'unknown', $error['message'] ?? 'Unknown error', $error['file'] ?? 'unknown', $error['line'] ?? 0, $error['context'] ?? 'unknown', $error['remote_ip'] ?? 'unknown', $error['request_uri'] ?? 'unknown', implode("\n", $error['backtrace'] ?? []) ); // Write to log file if (self::$logFile) { $result = file_put_contents(self::$logFile, $logMessage, FILE_APPEND | LOCK_EX); if ($result === false) { error_log("Failed to write to error log: " . self::$logFile); } } // Also log via PHP's error_log if our file fails if (!self::$logFile || !file_exists(self::$logFile)) { error_log("ErrorHandler: " . json_encode($error)); } } /** * Get backtrace safely */ private static function getBacktrace() { try { $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); $formatted = []; foreach ($backtrace as $i => $trace) { $formatted[] = sprintf( "#%d %s(%s): %s(%s)", $i, $trace['file'] ?? 'unknown', $trace['line'] ?? 'unknown', isset($trace['class']) ? $trace['class'] . '::' . $trace['function'] : $trace['function'] ?? 'unknown', isset($trace['args']) ? json_encode(count($trace['args'])) . ' args' : 'unknown args' ); } return $formatted; } catch (Exception $e) { return ["Failed to generate backtrace: " . $e->getMessage()]; } } /** * Render error page */ private static function renderErrorPage($error, $httpCode = 500) { http_response_code($httpCode); if (!headers_sent()) { header('Content-Type: text/html; charset=UTF-8'); header('Cache-Control: no-cache, no-store, must-revalidate'); } $title = $httpCode === 404 ? 'Page Not Found' : 'Server Error'; $message = $error['message'] ?? 'An unexpected error occurred'; echo " {$title}

{$title}

{$message}

"; if (Config::isEnvironment('development') && isset($error['file'])) { echo "
File: {$error['file']}
Line: {$error['line']}
Type: " . ($error['error_type'] ?? $error['type'] ?? 'unknown') . "
"; } echo "
"; } /** * Perform cleanup tasks on shutdown */ private static function performCleanup() { // Clean up expired sessions or temporary files if needed // This could be expanded based on application needs // Example: Clean up old temp files $tempDir = sys_get_temp_dir(); $pattern = $tempDir . '/dodgers_*'; foreach (glob($pattern) as $file) { // Remove files older than 1 hour if (filemtime($file) < time() - 3600) { @unlink($file); } } } /** * Handle API errors with JSON response */ public static function apiError($message, $code = 500, $details = null) { $error = [ 'success' => false, 'error' => $message, 'code' => $code, 'timestamp' => time() ]; if (Config::isEnvironment('development') && $details) { $error['details'] = $details; } http_response_code($code); header('Content-Type: application/json'); echo json_encode($error); } /** * Log security events */ public static function logSecurityEvent($event, $details = []) { $logEntry = [ 'type' => 'security_event', 'event' => $event, 'details' => $details, 'timestamp' => date('Y-m-d H:i:s'), 'remote_ip' => Security::getClientIP(), 'request_uri' => $_SERVER['REQUEST_URI'] ?? '', 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '', 'session_id' => session_id() ]; self::logError($logEntry); } /** * Log performance metrics */ public static function logPerformance($operation, $duration, $details = []) { $logEntry = [ 'type' => 'performance', 'operation' => $operation, 'duration' => $duration, 'details' => $details, 'timestamp' => date('Y-m-d H:i:s'), 'remote_ip' => Security::getClientIP(), 'session_id' => session_id() ]; self::logError($logEntry); } }