settings = $settings; } /** * Register exception and error handlers. */ public function register(): void { set_exception_handler([$this, 'handleException']); set_error_handler([$this, 'handleError']); register_shutdown_function([$this, 'handleShutdown']); } /** * Handle uncaught exceptions. * * @param \Throwable $exception */ public function handleException(\Throwable $exception): void { $this->renderResponse($exception); } /** * Handle PHP errors. * * @param int $level * @param string $message * @param string $file * @param int $line */ public function handleError(int $level, string $message, string $file, int $line): void { if (error_reporting() === 0) { return; // Suppressed } throw new \ErrorException($message, 0, $level, $file, $line); } /** * Handle shutdown events (fatal errors). */ public function handleShutdown(): void { $error = error_get_last(); if ($error !== null && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR], true)) { $this->renderResponse(new \ErrorException($error['message'], 0, $error['type'], $error['file'], $error['line'])); } } /** * Render error response. * * @param \Throwable $exception */ protected function renderResponse(\Throwable $exception): void { $debug = $this->settings->get('APP_DEBUG', false); $code = $exception->getCode() ?: 500; // Set HTTP response code http_response_code($code); // If AJAX or JSON requested, return JSON if ($this->isAjaxRequest()) { header('Content-Type: application/json'); echo json_encode([ 'error' => $exception->getMessage(), 'code' => $code, 'file' => $exception->getFile(), 'line' => $exception->getLine(), 'trace' => $debug ? $exception->getTrace() : null, ]); exit; } // Otherwise, render HTML error page header('Content-Type: text/html; charset=utf-8'); if ($debug) { // Show detailed error include $this->getDebugTemplate($exception); } else { // Show generic error page include $this->getGenericTemplate($code); } exit; } /** * Check if request is AJAX. * * @return bool */ protected function isAjaxRequest(): bool { return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'; } /** * Path to debug error template. * * @param \Throwable $exception * @return string */ protected function getDebugTemplate(\Throwable $exception): string { // We'll create a simple debug view ob_start(); ?> ??? ?? ???????

??? ??? ?? ???????

???????: getMessage()) ?>

?????: getCode() ?>
?????: getFile()) ?>:
?????: getLine() ?>
??????:
getTraceAsString())) ?>
??? <?= htmlspecialchars($code) ?>

???

??? ??? ??? ?????. ???? ???????? ??????.

?????? ???????? ??? ??????.

?????? ??? ?????? ????????