Вступление: Почему разработчики боятся белого экрана?
Каждый 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 (запись в лог или вывод на экран). На высоконагружен