Когда сайт падает с белым экраном или выдает непонятную ошибку — это бесит. И пользователя, и разработчика. Но ошибки в коде неизбежны. Вопрос в том, как их правильно ловить и обрабатывать. В PHP для этого есть целый арсенал: от старых добрых функций до современных исключений. В этой статье разберем, как сделать код устойчивым и дружелюбным к ошибкам.

Почему ошибки — это нормально

Ошибки в PHP бывают разные. Одни — наши промахи, другие — проблемы с окружением. Например, файл не найден, база данных упала, или разработчик забыл закрыть скобку. PHP не умеет читать мысли, поэтому он просто сообщает: «что-то пошло не так».

Раньше в PHP ошибки выводились прямо на экран. Это было удобно для отладки, но на боевом сайте — катастрофа. Пользователь видел технический текст, а иногда и пути к файлам. Хакеры такое любят. Поэтому обработка ошибок — это не про «красивый код», а про безопасность и стабильность.

Типы ошибок в PHP

В PHP есть несколько уровней ошибок. Они отличаются по серьёзности. Вот основные:

Тип ошибкиЧто значитПример
E_ERRORКритическая ошибка. Скрипт останавливается.Нехватка памяти, вызов несуществующей функции
E_WARNINGПредупреждение. Скрипт продолжает работу.Подключение несуществующего файла
E_NOTICEУведомление. Небольшая оплошность.Использование неопределённой переменной
E_PARSEСинтаксическая ошибка. Код не выполняется.Пропущенная точка с запятой

Понимание типов помогает решить, какие ошибки нужно обрабатывать, а какие — исправлять сразу.

Старый способ: функции для работы с ошибками

До появления исключений в PHP ошибки обрабатывали вручную. Основные инструменты — это error_reporting, set_error_handler и trigger_error.

error_reporting указывает, какие ошибки нужно показывать. Обычно на этапе разработки включают всё, а на боевом сайте — только критичные.

set_error_handler позволяет создать свою функцию, которая будет вызываться при любой ошибке. Это удобно, чтобы записывать ошибки в лог или отправлять уведомление разработчику.

Вот пример кастомного обработчика:

<?php
function myErrorHandler($level, $message, $file, $line) {
    $log = "[$level] $message in $file on line $line";
    file_put_contents('errors.log', $log . PHP_EOL, FILE_APPEND);
    return true;
}
set_error_handler('myErrorHandler');

// Теперь любая ошибка будет записана в файл
echo $undefinedVar;
?>

Этот метод работает, но у него есть минусы. Он не умеет перехватывать фатальные ошибки (E_ERROR) и синтаксические ошибки (E_PARSE). Для них нужен другой подход.

Исключения: современный подход

Исключения (exceptions) появились в PHP 5 и стали стандартом для обработки ошибок в объектно-ориентированном коде. Исключение — это объект класса Exception или его наследников. Когда возникает ошибка, мы «бросаем» исключение с помощью throw. А в другом месте «ловим» его с помощью try-catch.

Пример простого исключения:

<?php
function divide($a, $b) {
    if ($b == 0) {
        throw new Exception('Деление на ноль невозможно');
    }
    return $a / $b;
}

try {
    echo divide(10, 0);
} catch (Exception $e) {
    echo 'Ошибка: ' . $e->getMessage();
}
?>

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

Собственные классы исключений

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

Создаём класс-наследник от Exception:

<?php
class DatabaseException extends Exception {}
class ValidationException extends Exception {}

function connectToDatabase($dsn) {
    if (empty($dsn)) {
        throw new DatabaseException('DSN не может быть пустым');
    }
    // подключение...
}

try {
    connectToDatabase('');
} catch (DatabaseException $e) {
    echo 'Проблема с БД: ' . $e->getMessage();
} catch (Exception $e) {
    echo 'Неизвестная ошибка: ' . $e->getMessage();
}
?>

Здесь мы ловим сначала специфическое исключение, а потом общее. Порядок важен: если поставить catch (Exception $e) первым, он перехватит все исключения, и до DatabaseException дело не дойдёт.

Правило: Всегда ловите исключения от более конкретных к более общим. И не используйте catch (Exception $e) без необходимости — это скрывает настоящие проблемы.

Блок finally: что делать в любом случае

Иногда нужно выполнить код независимо от того, было исключение или нет. Например, закрыть соединение с базой данных или освободить ресурсы. Для этого существует блок finally. Он выполняется всегда — и после успешного выполнения try, и после catch.

<?php
function readFile($filename) {
    $handle = fopen($filename, 'r');
    if (!$handle) {
        throw new Exception('Не удалось открыть файл');
    }
    try {
        // читаем файл
        $content = fread($handle, filesize($filename));
        return $content;
    } finally {
        fclose($handle); // закроем файл в любом случае
    }
}
?>

Блок finally особенно полезен, когда у вас есть несколько точек выхода из функции или метода. Он гарантирует, что очистка произойдёт.

Как не надо обрабатывать ошибки

Есть несколько антипаттернов, которых стоит избегать:

  • Глушить ошибки с помощью @. Оператор @ подавляет вывод ошибок, но они всё равно происходят. Это как заклеить лампочку Check Engine — проблема не исчезнет.
  • Пустой catch. Если вы ловите исключение и ничего не делаете, это хуже, чем не ловить вообще. Вы теряете информацию об ошибке.
  • Выводить исключения пользователю. Никогда не показывайте пользователю технические детали ошибки. Используйте логирование и дружественные сообщения.
Лайфхак: На боевом сайте включите display_errors = Off в php.ini, а log_errors = On. Тогда ошибки будут записываться в лог, но не показываться пользователю.

Что в итоге

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

Студия WNDER