Error/Exception Flow

Centralized error/exception handling that stays production-safe.

On this page

Why Central Handling

In production, you want consistent behavior: log errors, return safe responses, and avoid leaking details. Central handling prevents each controller from doing its own error logic differently.

Set a Global Exception Handler

This handler logs the error and returns a safe message. In local mode, you may show more details.

<?php
$isLocal = (($_ENV["APP_ENV"] ?? "production") === "local");

set_exception_handler(function (Throwable $e) use ($isLocal) {
  error_log($e->getMessage());

  http_response_code(500);

  if ($isLocal) {
    echo "Exception: " . $e->getMessage();
    return;
  }

  echo "Internal Server Error";
});

Set an Error Handler

You can convert PHP warnings/notices into exceptions to handle them consistently.

<?php
set_error_handler(function (int $severity, string $message, string $file, int $line) {
  throw new ErrorException($message, 0, $severity, $file, $line);
});

Example: Controller Stays Clean

If central handlers exist, your controllers can focus on business logic and return proper status codes for expected errors only.

<?php
// Expected errors (like validation) can still be handled locally with 400 responses.
// Unexpected errors bubble up to the global handler.

Production Tip

Differentiate expected vs unexpected errors. Expected: validation, not found, forbidden (return 4xx). Unexpected: crashes, DB outages (return 500). Always log unexpected errors with enough context.