Как происходит обработка ошибок (errors) в PHP?

«Как происходит обработка ошибок (errors) в PHP?» — вопрос из категории PHP Core, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В PHP 8.x ошибки и исключения практически унифицированы. Большинство фатальных ошибок теперь выбрасываются как ErrorException. Моя практика обработки строится на следующих принципах:

1. Настройка среды: В production ошибки не показываются пользователю, но обязательно логируются.

// .env.production
APP_DEBUG=false

// В коде или конфиге
ini_set('display_errors', '0');
error_reporting(E_ALL); // Ловим всё
ini_set('log_errors', '1');
ini_set('error_log', '/var/log/php/errors.log');

2. Преобразование ошибок в исключения: Это позволяет обрабатывать все ошибки единообразно через try-catch.

set_error_handler(function($severity, $message, $file, $line) {
    if (!(error_reporting() & $severity)) {
        return false; // Пропускаем ошибки, которые error_reporting отфильтровал
    }
    throw new ErrorException($message, 0, $severity, $file, $line);
});

// Пример: теперь warning при делении на ноль станет исключением
try {
    $result = 10 / 0;
} catch (ErrorException $e) {
    Log::error('Division error caught as exception', ['exception' => $e]);
}

3. Обработка фатальных ошибок: Для ошибок, которые нельзя преобразовать в исключения (например, ошибка выделения памяти), используется register_shutdown_function:

register_shutdown_function(function() {
    $error = error_get_last();
    if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR])) {
        // Логируем критическую ошибку
        Log::critical('Fatal shutdown', $error);
        // Для API можно отправить JSON-ответ
        if (str_contains($_SERVER['HTTP_ACCEPT'] ?? '', 'application/json')) {
            header('Content-Type: application/json');
            echo json_encode(['error' => 'Internal Server Error']);
        }
    }
});

4. Практический пример в Laravel Middleware: Создавал middleware для глобального отлова ошибок валидации и преобразования их в стандартизированный JSON-ответ:

public function handle($request, Closure $next)
{
    $response = $next($request);

    if ($response->exception instanceof ValidationException) {
        return response()->json([
            'success' => false,
            'errors' => $response->exception->errors()
        ], 422);
    }

    return $response;
}

Ключевой вывод: в современном PHP стоит стремиться к тому, чтобы вся обработка шла через механизм исключений, что делает код чище и предсказуемее.