getMessage()); } // 3. Configure Error Reporting based on environment $isDebug = filter_var(getenv('APP_DEBUG') ?: true, FILTER_VALIDATE_BOOLEAN); if ($isDebug) { ini_set('display_errors', '1'); ini_set('display_startup_errors', '1'); error_reporting(E_ALL); } else { ini_set('display_errors', '0'); error_reporting(0); } // 4. Global Uncaught Exception Handler // Catches any unhandled exception anywhere in the app and returns a clean JSON error // instead of leaking PHP stack traces to the browser. set_exception_handler(function (\Throwable $e) { $isDebug = filter_var(getenv('APP_DEBUG') ?: true, FILTER_VALIDATE_BOOLEAN); error_log('[EXCEPTION] ' . get_class($e) . ': ' . $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine()); if (!headers_sent()) { header('Content-Type: application/json; charset=utf-8'); http_response_code(500); } $body = ['error' => 'Internal Server Error']; // In debug mode, expose details to the developer only if ($isDebug) { $body['debug'] = [ 'exception' => get_class($e), 'message' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine(), ]; } echo json_encode($body, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); exit(1); });