Ловим баги в коде: как включить вывод ошибок PHP (и не тормозить сайт)

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Вступление: Почему разработчики боятся белого экрана?

Каждый PHP-разработчик хотя бы раз в жизни сталкивался с ситуацией: код вроде бы написан, но вместо результата — пустая страница. Ни ошибки, ни предупреждения. Только тишина и холодный пот. Знакомо?

На Stack Overflow вопрос «How do I get PHP errors to display?» набрал тысячи просмотров и сотни ответов. Это не случайно: умение правильно включать и обрабатывать ошибки — базовый навык, который экономит часы отладки. Но есть нюанс: неправильная настройка может не только не помочь, но и снизить производительность вашего сайта или, что еще хуже, открыть уязвимости.

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

Краткий ликбез: какие бывают ошибки PHP?

Прежде чем включать отображение, полезно понимать, с чем мы имеем дело. PHP генерирует несколько уровней ошибок:

  • E_ERROR — фатальная ошибка. Скрипт останавливается. Пример: нехватка памяти, вызов несуществующего класса.
  • E_WARNING — нефатальная. Скрипт продолжает работу, но что-то пошло не так. Пример: include файла, которого нет.
  • E_NOTICE — уведомление. Обычно о незначительных проблемах (неопределенная переменная).
  • E_PARSE — синтаксическая ошибка. Возникает до выполнения кода, поймать её в runtime сложно.
  • E_ALL — включает все уровни, кроме E_STRICT (до PHP 8.0).

Запомните: на этапе разработки мы хотим видеть все ошибки. На боевом сервере — только критичные, и то в логах, а не на экране.

Способ №1: Быстрый и грязный — прямо в коде

Самый простой метод для одноразовой отладки — вставить в начало скрипта две магические строки:

<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
?>

Что здесь происходит?

  • display_errors — включает вывод ошибок на экран.
  • display_startup_errors — показывает ошибки, возникшие при запуске PHP (например, в php.ini).
  • error_reporting(E_ALL) — устанавливает уровень отчетности: показывать всё.

Этот способ идеален для одного файла, который вы отлаживаете. Но есть минусы: вы должны помнить удалить эти строки перед выкладкой на продакшн. Иначе рискуете показать пользователям «кишки» вашего приложения.

Способ №2: Настройка php.ini — глобально и навсегда

Если вы работаете на локальной машине или контролируете сервер, проще отредактировать php.ini. Найдите этот файл (обычно в /etc/php/ или /usr/local/etc/php/) и измените следующие директивы:

display_errors = On
display_startup_errors = On
error_reporting = E_ALL

После изменений не забудьте перезапустить веб-сервер:

sudo systemctl restart apache2
# или
sudo systemctl restart nginx php8.1-fpm

Важно: на продакшн-сервере display_errors должен быть Off. Вместо этого настройте логирование ошибок в файл:

display_errors = Off
log_errors = On
error_log = /var/log/php_errors.log
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT

Это снижает нагрузку на вывод и защищает данные сайта.

Способ №3: Через .htaccess — для shared-хостинга

Если у вас нет доступа к php.ini (например, дешёвый хостинг), используйте файл .htaccess в корне сайта:

php_flag display_errors on
php_flag display_startup_errors on
php_value error_reporting 32767

Число 32767 — это значение E_ALL для PHP 5.4+. На PHP 8.0+ можно использовать E_ALL напрямую:

php_value error_reporting E_ALL

Этот метод работает, если хостинг разрешает переопределение директив через .htaccess. Не все хосты это поддерживают.

Способ №4: Через .user.ini — современная альтернатива

Начиная с PHP 5.3, можно использовать файл .user.ini в директории скрипта. Он работает аналогично .htaccess, но не зависит от Apache. Подходит для Nginx + FPM:

display_errors = On
error_reporting = E_ALL

Файл читается при каждом запросе, поэтому не требует перезагрузки сервера.

Способ №5: Для тех, кто пишет фреймворки — собственный обработчик

В современных проектах (Laravel, Symfony) используется собственный обработчик ошибок. Но если вы пишете с нуля, можно создать мощный инструмент:

<?php
function customErrorHandler($errno, $errstr, $errfile, $errline) {
    if (!(error_reporting() & $errno)) {
        // Этот код ошибки не входит в error_reporting
        return;
    }
    echo "<b>Ошибка:</b> [$errno] $errstr<br>";
    echo "Файл: $errfile, строка: $errline<br>";
    echo "Стек вызовов:<pre>" . print_r(debug_backtrace(), true) . "</pre>";
}

set_error_handler("customErrorHandler");

// Теперь все ошибки проходят через нашу функцию
echo $undefined_variable; // Notice
?>

Этот подход даёт полный контроль над форматом вывода. Можно добавить JSON-вывод для API, логирование в БД или отправку уведомлений в Telegram.

Производительность: как не убить сайт ошибками

Многие думают: «Включу все ошибки — и будет счастье». Но вот три подводных камня:

1. Display_errors на продакшне = дыра в безопасности

Вывод ошибок на экран в публичной среде может раскрыть пути к файлам, структуру БД и даже пароли. Никогда не оставляйте display_errors = On на боевом сервере.

2. E_NOTICE и E_WARNING — скрытые тормоза

Каждое предупреждение генерирует дополнительный I/O (запись в лог или вывод на экран). На высоконагружен

Блоги

Рекомендаций по книгам