File manager - Edit - /home/webapp69.cm.in.th/u69319090028/Shop/app/Core/ErrorHandler.php
Back
<?php /** * Global Error & Exception Handler * Intercepts PHP errors, uncaught exceptions, and fatal shutdown errors * Provides structured JSON responses for APIs and elegant views for web users * Masks system paths and SQL details in production */ require_once __DIR__ . '/Exceptions/AppException.php'; require_once __DIR__ . '/Exceptions/ValidationException.php'; require_once __DIR__ . '/Exceptions/AuthenticationException.php'; require_once __DIR__ . '/Exceptions/AuthorizationException.php'; require_once __DIR__ . '/Exceptions/NotFoundException.php'; require_once __DIR__ . '/Exceptions/ConflictException.php'; require_once __DIR__ . '/Exceptions/RateLimitException.php'; require_once __DIR__ . '/Exceptions/BusinessRuleException.php'; require_once __DIR__ . '/Exceptions/CsrfException.php'; require_once __DIR__ . '/../Helpers/Logger.php'; require_once __DIR__ . '/../Helpers/Security.php'; class ErrorHandler { private static bool $registered = false; public static function register(): void { if (self::$registered) { return; } // Set error reporting error_reporting(E_ALL); // Register Handlers set_error_handler([self::class, 'handleError']); set_exception_handler([self::class, 'handleException']); register_shutdown_function([self::class, 'handleShutdown']); self::$registered = true; } /** * Convert PHP Errors to ErrorException */ public static function handleError(int $severity, string $message, string $file, int $line): bool { if (!(error_reporting() & $severity)) { return false; } throw new ErrorException($message, 0, $severity, $file, $line); } /** * Uncaught Exception Handler */ public static function handleException(Throwable $e): void { $statusCode = 500; $errorCode = 'INTERNAL_SERVER_ERROR'; $userMessage = 'เกิดข้อผิดพลาดขึ้นในระบบ กรุณาลองใหม่อีกครั้ง'; $details = []; if ($e instanceof AppException) { $statusCode = $e->getStatusCode(); $errorCode = $e->getErrorCode(); $userMessage = $e->getMessage(); $details = $e->getContext(); if ($e instanceof ValidationException) { $details = ['errors' => $e->getErrors()]; } elseif ($e instanceof RateLimitException) { header('Retry-After: ' . $e->getRetryAfter()); } } elseif ($e instanceof PDOException) { $statusCode = 500; $errorCode = 'DATABASE_ERROR'; $userMessage = 'เกิดข้อผิดพลาดในการเชื่อมต่อฐานข้อมูล กรุณาลองใหม่อีกครั้ง'; Logger::critical("Database Exception: " . $e->getMessage(), [ 'code' => $e->getCode(), 'trace' => $e->getTraceAsString() ]); } else { Logger::error("Unhandled Exception: " . $e->getMessage(), [ 'type' => get_class($e), 'file' => $e->getFile(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString() ]); } // Check if debug mode is enabled $appConfig = file_exists(__DIR__ . '/../../config/app.php') ? require __DIR__ . '/../../config/app.php' : []; $isDebug = !empty($appConfig['debug']); // Check if API / AJAX request $isApi = self::isJsonRequest(); http_response_code($statusCode); if ($isApi) { header('Content-Type: application/json; charset=utf-8'); $response = [ 'success' => false, 'error' => [ 'code' => $errorCode, 'message' => $userMessage, 'details' => $details ] ]; if ($isDebug && $statusCode === 500) { $response['debug'] = [ 'exception' => get_class($e), 'message' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine() ]; } echo json_encode($response, JSON_UNESCAPED_UNICODE); exit; } // Render Web View self::renderErrorView($statusCode, $userMessage, $errorCode, $details, $e, $isDebug); exit; } /** * Fatal shutdown handler */ public static function handleShutdown(): void { $error = error_get_last(); if ($error !== null && in_array($error['type'], [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE], true)) { Logger::critical("Fatal Shutdown Error: " . $error['message'], [ 'file' => $error['file'], 'line' => $error['line'] ]); if (self::isJsonRequest()) { http_response_code(500); header('Content-Type: application/json; charset=utf-8'); echo json_encode([ 'success' => false, 'error' => [ 'code' => 'FATAL_ERROR', 'message' => 'เกิดข้อผิดพลาดร้ายแรงในระบบ' ] ], JSON_UNESCAPED_UNICODE); exit; } http_response_code(500); $viewFile = __DIR__ . '/../../views/errors/500.php'; if (file_exists($viewFile)) { require $viewFile; } else { echo "<h1>500 Internal Server Error</h1><p>เกิดข้อผิดพลาดขึ้นในระบบ</p>"; } } } private static function isJsonRequest(): bool { $uri = $_SERVER['REQUEST_URI'] ?? ''; $accept = $_SERVER['HTTP_ACCEPT'] ?? ''; $xRequested = $_SERVER['HTTP_X_REQUESTED_WITH'] ?? ''; if (strpos($uri, '/api/') !== false) { return true; } if (strpos($accept, 'application/json') !== false) { return true; } if (strtolower($xRequested) === 'xmlhttprequest') { return true; } return false; } private static function renderErrorView(int $statusCode, string $message, string $errorCode, array $details, Throwable $e, bool $isDebug): void { $viewFile = __DIR__ . '/../../views/errors/' . $statusCode . '.php'; if (!file_exists($viewFile)) { $viewFile = __DIR__ . '/../../views/errors/500.php'; } // Variables made available to the error view $pageTitle = "Error {$statusCode} - CARGOO"; $errorDetails = $details; $exception = $e; if (file_exists($viewFile)) { require $viewFile; } else { echo "<h1>Error {$statusCode}</h1><p>" . htmlspecialchars($message) . "</p>"; } } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.38 |
proxy
|
phpinfo
|
Settings