Обработка ошибок и исключений в PHP: полный гайд

JavaScript · 19.07.2026 · 1 мин чтения

Правильная обработка ошибок и исключений — основа надёжного PHP-приложения. Разбираем try-catch, пользовательские исключения и логирование.

Схема обработки ошибок и исключений в PHP с try-catch-finally

Обработка ошибок и исключений — ключевой аспект написания надёжного PHP-кода. Без правильной системы обработки ошибок приложение может падать, оставлять разработчика без информации о проблемах и создавать уязвимости.

Ошибки vs Исключения

В PHP есть два понятия: ошибки (errors) — фатальные проблемы, и исключения (exceptions) — контролируемые ситуации, которые можно перехватить и обработать.

Исключения: try-catch-finally

Базовый синтаксис

exec('SELECT * FROM nonexistent_table');
} catch (\PDOException e) {
 error_log('Database error: ' . e->getMessage());
 echo 'Произошла ошибка базы данных. Попробуйте позже.';
} catch (\Exception e) {
 error_log('General error: ' . e->getMessage());
 echo 'Произошла непредвиденная ошибка.';
} finally {
 // Выполняется всегда, даже если было исключение
 echo 'Завершение выполнения';

?>

Пользовательские исключения

Создавайте свои классы исключений для лучшей организации кода:

errors=errors;

 
 public function getErrors(): array {
 return this->errors;



class DatabaseException extends \Exception {
 public function __construct(string message, int 
code=0,?
Throwableprevious = null) {
 parent::__construct(
message,code, previous);



// Использование
class UserService {
 public function createUser(array data): int {
 if (empty(data['email'])) {
 throw new ValidationException(['email' => 'Email is required']);

 
 try {
 stmt = this->db->prepare('INSERT INTO users (email) VALUES (?)');
 stmt->execute([data['email']]);
 return (int) this->db->lastInsertId();
 } catch (\PDOException e) {
 throw new DatabaseException('Failed to create user: ' . e->getMessage(), 500, e);

service = new UserService();
try {
 
id=service->createUser([]);
} catch (ValidationException e) {
 http_response_code(422);
 echo json_encode(['errors' => e->getErrors()]);
} catch (DatabaseException e) {
 http_response_code(500);
 error_log(e->getMessage());
 echo json_encode(['error' => 'Internal server error']);

?>

Глобальный обработчик исключений

Установите обработчик для всех неперехваченных исключений:

getMessage());
 error_log('Stack trace: ' . e->getTraceAsString());
 
 http_response_code(500);
 echo json_encode([
 'error' => 'Internal server error',
 'message' => _ENV['APP_ENV'] === 'dev' ? e->getMessage() : null
 ]);
});

set_error_handler(function (int errno, string 
errstr,stringerrfile, int errline) {
 throw new \ErrorException(errstr, 0, 
errno,errfile, errline);
});

register_shutdown_function(function () {
 error = error_get_last();
 if (error !== null && in_array(error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR])) {
 error_log('Fatal error: ' . 
error[ 

 message 

 ]. 

 in 

 .error['file'] . ':' . error['line']);

});
?>

Логирование ошибок

Настраиваем логирование с Monolog:

<?php
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

logger = new Logger('app');
logger->pushHandler(new StreamHandler('/var/log/app.log', Logger::ERROR));

try {
 // Код, который может вызвать ошибку
 result = riskyOperation();
} catch (\Exception e) {
 logger->error('Operation failed', [
 'message' => e->getMessage(),
 'code' => e->getCode(),
 'file' => e->getFile(),
 'line' => e->getLine(),
 'trace' => e->getTraceAsString()
 ]);
 throw e;

?>

Стратегии обработки ошибок

Тип ошибкиСтратегияПример
Валидация данныхВыбросить ValidationExceptionПользователь ввёл некорректный email
БД недоступнаПовторная попытка или возврат 503Проблемы с подключением к БД
API стороннего сервисаFallback (кэш/заглушка)Не отвечает внешний API
Фатальная ошибкаЛогирование + корректный ответОтсутствует файл конфигурации

Обработка ошибок в PDO

setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);

// Вместо проверки ошибок через if

stmt=pdo->prepare('SELECT * FROM users WHERE id = ?');

stmt−>execute([userId]);

if (stmt->rowCount() === 0) {
 throw new \RuntimeException('User not found');


user = stmt->fetch(\PDO::FETCH_ASSOC);
?>

Retry логика (повторные попытки)

Для временных сбоев полезно реализовать повторные попытки:

<?php
function withRetry(callable operation, int 
maxAttempts=3,intdelay = 100): mixed {
 attempt = 0;
 lastException = null;
 
 while (
attemptquery('SELECT COUNT(*) FROM users')->fetchColumn();
 }, 5, 100);
} catch (\Exception e) {
 error_log('Failed after 5 attempts: ' . e->getMessage());
 result = 0; // Fallback значение

?>

Итог

  • Всегда используйте try-catch для контролируемых операций
  • Создавайте пользовательские исключения для разных типов ошибок
  • Настраивайте глобальные обработчики для неперехваченных ошибок
  • Логируйте ошибки с достаточной информацией для отладки
  • Используйте retry-механизмы для временных сбоев
JavaScript Frontend Linting
← Ко всем статьям

Читайте также