«Белый экран смерти» в PHP: как заставить ошибки говорить?
Каждый PHP-разработчик сталкивался с ситуацией: код вроде бы работает, но на экране — пустота. Ни сообщения, ни предупреждения. Только белый лист и чувство лёгкого безумия. Знакомо? Это классический «белый экран смерти» (White Screen of Death — WSOD). Чаще всего проблема в том, что вывод ошибок PHP отключён.
На Stack Overflow вопрос «How do I get PHP errors to display?» собрал тысячи просмотров. И это не случайно: настройка отображения ошибок — база, которую обязан знать каждый. Но просто включить display_errors — мало. Нужно понимать, как это влияет на производительность и безопасность вашего приложения.
В этой статье мы разберём:
- Как включить ошибки PHP в разных средах (локально, на сервере, в фреймворках);
- Как настроить
error_reportingдля оптимальной отладки; - Почему вывод ошибок на продакшене — плохая идея;
- Как логировать ошибки без потери производительности.
Поехали!
Почему PHP не показывает ошибки? Три главные причины
Прежде чем лезть в код, давайте поймём, почему ошибки могут быть скрыты. PHP — гибкий язык, и его поведение зависит от настроек php.ini, самого скрипта и серверного окружения.
1. Настройки php.ini
Главный виновник — директива display_errors. По умолчанию на многих хостингах она установлена в Off. Это сделано для безопасности: на продакшене показывать пользователю стек вызовов — плохая практика.
2. Функция error_reporting()
Даже если display_errors включён, уровень ошибок может быть слишком низким. Например, error_reporting(0) скроет всё. Или вы можете случайно отфильтровать нужные типы ошибок (E_NOTICE, E_WARNING).
3. Ошибки до выполнения скрипта
Самые коварные — синтаксические ошибки в php.ini или в подключаемых файлах. Если PHP не может даже запустить скрипт, он не дойдёт до ваших настроек. В таких случаях помогает проверка синтаксиса через консоль: php -l file.php.
Как включить вывод ошибок PHP: пошаговое руководство
Способ 1. Редактирование php.ini (постоянные настройки)
Самый надёжный способ — изменить php.ini. Найдите файл (обычно он лежит в /etc/php/ или /usr/local/etc/php/) и установите:
display_errors = On
error_reporting = E_ALL
После изменений обязательно перезагрузите сервер:
sudo service apache2 restart
# или для nginx + php-fpm:
sudo service php8.1-fpm restart
Плюсы: настройка действует для всех скриптов на сервере.
Минусы: требует доступа к серверу; не подходит для общего хостинга.
Способ 2. Через .htaccess (для Apache)
Если у вас нет доступа к php.ini, но есть Apache, используйте .htaccess:
php_flag display_errors on
php_value error_reporting 32767 # E_ALL
Важно: этот метод работает, если на сервере разрешена директива AllowOverride.
Способ 3. Прямо в скрипте (для отладки)
Самый гибкий вариант — включить ошибки в конкретном файле. Идеально для разработки:
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// Ваш код
echo $undefined_variable; // Вызовет Notice
?>
Обратите внимание на display_startup_errors — он ловит ошибки, возникающие до выполнения скрипта (например, при подключении файлов).
Способ 4. Специфика фреймворков (Laravel, Symfony, WordPress)
Современные фреймворки имеют свои механизмы. В Laravel откройте .env и установите:
APP_DEBUG=true
APP_ENV=local
В WordPress добавьте в wp-config.php:
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', true);
Оптимизация: почему нельзя просто включить display_errors на продакшене
Казалось бы — включил и работаешь. Но на боевом сервере вывод ошибок на экран — это угроза безопасности и производительности.
- Утечка информации: стек вызовов может показать пути к файлам, версии библиотек, структуру БД. Злоумышленники используют это для атак.
- Снижение скорости: каждая ошибка генерирует вывод. Если ошибок много (например, сотни E_NOTICE в цикле), это заметно замедляет страницу.
- Плохой UX: пользователи не должны видеть технические сообщения.
Решение — логировать ошибки в файл, а не выводить на экран. Это и безопасно, и удобно для отладки.
Как настроить логирование без потери производительности
<?php
// Включаем логирование
ini_set('log_errors', 1);
ini_set('error_log', '/var/log/php_errors.log');
// Отключаем вывод на экран (для продакшена)
ini_set('display_errors', 0);
// Но отслеживаем все ошибки
error_reporting(E_ALL);
// Пример: намеренная ошибка
trigger_error("Это предупреждение уйдёт в лог", E_USER_WARNING);
?>
Совет по производительности: не пишите логи на медленный диск (например, NFS). Используйте локальный SSD или сервисы вроде syslog. В высоконагруженных проектах рассмотрите мониторинг ошибок через Sentry, Rollbar или Grafana Loki — они не блокируют выполнение скрипта и дают аналитику.
Продвинутые техники: как не пропустить критическую ошибку
Стандартный error_reporting(E_ALL) ловит почти всё. Но есть нюансы:
- Фатальные ошибки (E_ERROR): их невозможно обработать стандартным обработчиком. Используйте
register_shutdown_function().