PHPFlowPHP, MySQL, Laravel и JavaScript

Вывод ошибок PHP: как включить display_errors и error_reporting

Обновлено:

Коротко

Чтобы включить вывод ошибок PHP, добавьте в начало скрипта ini_set('display_errors', '1') и error_reporting(E_ALL) или пропишите display_errors = On и error_reporting = E_ALL в php.ini и перезапустите веб-сервер. Ошибки синтаксиса так не покажутся: для них нужен php.ini, .htaccess или проверка командой php -l. На рабочем сайте ошибки не выводят на экран, а пишут в лог.

Содержание
  1. Быстрый способ: три строки в начале скрипта
  2. Почему ошибки не показываются: причины и решения
  3. Как включить вывод ошибок в php.ini
  4. Вывод ошибок через .htaccess и .user.ini
  5. Уровни error_reporting и что они значат
  6. Лог ошибок PHP: где искать и как читать
  7. Ошибки в консоли и проверка синтаксиса
  8. Свой обработчик ошибок и исключений
  9. Как убрать предупреждение, а не спрятать его
  10. Вывод ошибок в Laravel и других фреймворках
  11. Почему на рабочем сайте вывод выключают

Быстрый способ: три строки в начале скрипта

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

Код включения display_errors и error_reporting в начале index.php
Строки включения вывода ошибок ставятся в самое начало файла, до подключения остальных скриптов
<?php
declare(strict_types=1);

// показать все ошибки, предупреждения и уведомления
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);

require __DIR__ . '/config.php';
  • display_errors отвечает за то, показывать ли сообщение в браузере или консоли;
  • display_startup_errors добавляет ошибки, которые случились при запуске PHP (например, не загрузилось расширение);
  • error_reporting(E_ALL) задаёт, какие уровни ошибок вообще учитывать. E_ALL означает "все".

Если в файле синтаксическая ошибка (забытая точка с запятой, лишняя скобка), PHP не выполнит ни одной строки, в том числе ini_set(). Вы увидите белый экран или ошибку 500. Такие ошибки включаются только в php.ini, .htaccess или .user.ini, а быстрее всего находятся командой php -l.

Почему ошибки не показываются: причины и решения

Если после настройки страница всё равно пустая, пройдитесь по таблице. Чаще всего правят не тот php.ini или забывают перезапустить сервер.

ПричинаКак исправить
Изменён не тот php.iniОткройте phpinfo() и посмотрите строку "Loaded Configuration File"
Сервер не перезапущенПерезапустите Apache, PHP-FPM или локальный сервер целиком
Ошибка синтаксиса в файлеПроверьте файл командой php -l index.php
Ниже в коде стоит error_reporting(0)Найдите поиском по проекту и уберите или закомментируйте
Перед функцией стоит @Оператор @ глушит сообщение, уберите его на время отладки
Фреймворк перехватывает ошибкиВключите режим отладки фреймворка (в Laravel APP_DEBUG=true)
Хостинг запрещает выводВключите опцию в панели или смотрите лог ошибок

Если вместо страницы приходит код ответа 500, разберитесь с ним отдельно по инструкции про ошибку 500 Internal Server Error: там собраны причины, не связанные с PHP-кодом.

Как включить вывод ошибок в php.ini

Настройка в php.ini действует на все скрипты сразу и показывает даже ошибки синтаксиса. Сначала узнайте, какой файл реально загружен: у PHP в консоли и у веб-сервера он может быть разным.

  1. Выполните в терминале php --ini и посмотрите строку "Loaded Configuration File".
  2. Для сайта создайте временный файл с phpinfo(), откройте его в браузере и найдите ту же строку. После проверки файл удалите.
  3. Откройте найденный php.ini в редакторе.
  4. Найдите директивы display_errors и error_reporting через поиск Ctrl + F.
  5. Задайте значения как в примере ниже и сохраните файл.
  6. Перезапустите веб-сервер или PHP-FPM.
Вывод команды php --ini с путём к загруженному php.ini
Команда php --ini показывает, какой php.ini загружен на самом деле

Для разработки подойдёт такой набор:

; php.ini для локальной разработки
display_errors = On
display_startup_errors = On
error_reporting = E_ALL
log_errors = On
error_log = "C:\xampp\php\logs\php_error_log"
html_errors = On

Для рабочего сервера значения другие: на экран ничего, всё в лог.

; php.ini для продакшена
display_errors = Off
display_startup_errors = Off
error_reporting = E_ALL & ~E_DEPRECATED
log_errors = On
error_log = /var/log/php/error.log

В поставке PHP есть два образца: php.ini-development и php.ini-production. Первый уже настроен на показ ошибок, второй на их скрытие. Подробнее о расположении файла в разных системах написано в статье где находится php.ini.

Настройки display_errors, error_reporting и error_log в php.ini
Директивы вывода и записи ошибок в php.ini для локальной разработки

Перезапуск после правки

Изменения php.ini подхватываются только после перезапуска процесса, который выполняет PHP:

# Ubuntu, PHP-FPM (номер версии подставьте свой)
sudo systemctl restart php8.4-fpm

# Ubuntu, Apache с модулем PHP
sudo systemctl restart apache2

# проверить, что значение применилось
php -i | grep display_errors

В XAMPP нажмите "Stop" и затем "Start" напротив Apache в XAMPP Control Panel. Как устроен сам пакет и где лежат его конфиги, описано в инструкции по установке XAMPP на Windows.

Вывод ошибок через .htaccess и .user.ini

Если доступа к php.ini нет, как на обычном хостинге, вывод ошибок включают для одной папки сайта. Способ зависит от того, как PHP подключён к веб-серверу.

Apache с модулем mod_php

Добавьте в .htaccess в корне сайта:

# работает только при PHP как модуле Apache
php_flag display_errors on
php_flag display_startup_errors on
php_value error_reporting -1

Значение -1 включает все биты, то есть то же, что E_ALL. Имена констант в .htaccess не работают, только числа.

Если PHP работает через PHP-FPM или FastCGI, директивы php_flag и php_value в .htaccess вызывают ошибку 500. Удалите их и используйте .user.ini. Другие полезные правила для этого файла собраны в материале про настройки .htaccess.

PHP-FPM и хостинг: файл .user.ini

Файл .user.ini кладут в корень сайта. Синтаксис как у php.ini:

display_errors = On
error_reporting = E_ALL
log_errors = On
error_log = /home/user/site.ru/logs/php_errors.log

PHP перечитывает .user.ini не сразу, а раз в user_ini.cache_ttl секунд (по умолчанию 300). Если изменений не видно, подождите пять минут или перезапустите PHP-FPM. Во многих панелях хостинга тот же переключатель есть в разделе настроек PHP для сайта.

Уровни error_reporting и что они значат

Функция error_reporting() принимает битовую маску. Уровни комбинируются операторами | (добавить) и & ~ (исключить).

КонстантаЧто означаетСкрипт продолжит работу
E_ERRORФатальная ошибка: нет памяти, вызов несуществующей функцииНет
E_PARSEОшибка разбора кода, синтаксисНет
E_WARNINGПредупреждение: не найден файл в include, деление на ноль в старом кодеДа
E_NOTICEЗамечание о потенциальной проблемеДа
E_DEPRECATEDФункция устарела и пропадёт в будущих версияхДа
E_ALLВсе уровни сразуЗависит от ошибки
// все ошибки, кроме сообщений об устаревших функциях
error_reporting(E_ALL & ~E_DEPRECATED);

// только серьёзные ошибки
error_reporting(E_ERROR | E_PARSE);

// узнать текущее значение
echo error_reporting();

Константа E_STRICT в PHP 8.4 объявлена устаревшей, в новых конфигах её не указывайте. Обращение к неопределённой переменной или ключу массива с PHP 8.0 даёт уже E_WARNING, а не E_NOTICE, поэтому после обновления старых проектов предупреждений обычно становится больше.

Начиная с PHP 8.5 фатальные ошибки выводятся вместе с трассировкой вызовов: сразу видно, из какой функции пришёл вызов. Отвечает за это директива fatal_error_backtraces, по умолчанию она включена.

Лог ошибок PHP: где искать и как читать

Лог полезнее экрана: в нём остаются ошибки фоновых задач, AJAX-запросов и редиректов, которые в браузере не видны. Запись включают директивы log_errors = On и error_log = путь. Если error_log не задан, PHP отдаёт сообщения веб-серверу, и они попадают в его журнал.

ОкружениеГде лежит лог
XAMPP (Windows)C:\xampp\php\logs\php_error_log и C:\xampp\apache\logs\error.log
Ubuntu, Apache/var/log/apache2/error.log
Ubuntu, Nginx + PHP-FPM/var/log/nginx/error.log и лог пула FPM
DockerВывод контейнера: docker logs имя_контейнера
ХостингПапка logs рядом с сайтом или раздел логов в панели

Удобно держать лог открытым и смотреть новые строки по мере обновления страницы:

tail -f /var/log/php/error.log

# последние 50 строк только с фатальными ошибками
grep "Fatal error" /var/log/php/error.log | tail -n 50

В PowerShell аналог команды выглядит так: Get-Content C:\xampp\php\logs\php_error_log -Wait -Tail 20.

Вывод tail -f с предупреждением и фатальной ошибкой PHP
Новые записи в логе ошибок PHP появляются сразу после обновления страницы

Своя запись в лог через error_log()

Функция error_log() пишет строку в тот же журнал или в отдельный файл. Это удобно для отладочных сообщений, которые не должны попасть на экран.

$userId = 42;
error_log("Не найден профиль пользователя {$userId}");

// запись в свой файл: тип 3, перевод строки добавляем сами
error_log(date('c') . " оплата не прошла\n", 3, __DIR__ . '/logs/pay.log');

Ошибки в консоли и проверка синтаксиса

В CLI-режиме PHP использует свой php.ini, и вывод ошибок там часто уже включён. Если нет, значение задают прямо в команде ключом -d:

# запустить скрипт с показом всех ошибок
php -d display_errors=1 -d error_reporting=-1 cron/import.php

# проверить синтаксис без выполнения
php -l public/index.php

Команда php -l не запускает код, а только разбирает его. Это самый быстрый способ найти забытую скобку, из-за которой сайт показывает белый экран.

Проверка файла командой php -l до и после исправления
Проверка синтаксиса командой php -l находит ошибку, из-за которой сайт показывает белый экран

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

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

// любые предупреждения и замечания превращаем в исключения
set_error_handler(function (int $level, string $message, string $file, int $line): bool {
    if (!(error_reporting() & $level)) {
        return false; // уровень отключён или стоит @
    }
    throw new ErrorException($message, 0, $level, $file, $line);
});

// необработанные исключения: пишем в лог, пользователю короткий ответ
set_exception_handler(function (Throwable $e): void {
    error_log((string) $e);
    http_response_code(500);
    echo ini_get('display_errors') === '1'
        ? '<pre>' . htmlspecialchars((string) $e) . '</pre>'
        : 'Произошла ошибка, попробуйте позже';
});

Фатальные ошибки вроде нехватки памяти обработчик не поймает. Для них регистрируют функцию через register_shutdown_function() и внутри проверяют error_get_last().

Как убрать предупреждение, а не спрятать его

Частый запрос "php include убрать ошибку" обычно означает предупреждение Failed to open stream. Глушить его оператором @ или error_reporting(0) плохо: проблема остаётся, а следов не будет. Лучше устранить причину.

// путь от папки текущего файла, а не от рабочей директории
$file = __DIR__ . '/parts/header.php';

if (is_file($file)) {
    require $file;
} else {
    error_log("Нет файла шаблона: {$file}");
}

// неопределённый ключ массива: значение по умолчанию вместо предупреждения
$page = $_GET['page'] ?? 1;

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

Вывод ошибок в Laravel и других фреймворках

Фреймворки ставят свои обработчики, поэтому настройки php.ini у них работают частично. В Laravel режим отладки включается в файле .env:

APP_ENV=local
APP_DEBUG=true

С APP_DEBUG=true Laravel показывает подробную страницу ошибки, с false пользователю показывается короткая страница 500, а детали уходят в storage/logs/laravel.log. После правки .env на сервере с кешем конфигурации выполните php artisan config:clear. В Symfony похожую роль играют переменные APP_ENV=dev и APP_DEBUG=1.

Почему на рабочем сайте вывод выключают

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

  • локально и на тестовом сервере: display_errors = On, error_reporting = E_ALL;
  • на рабочем сайте: display_errors = Off, log_errors = On, лог в папке вне веб-корня;
  • временно включённый вывод через .htaccess или .user.ini после отладки обязательно верните обратно.

Не оставляйте в папке сайта файлы с phpinfo(): они показывают всю конфигурацию сервера любому посетителю.

Частые вопросы

Как включить отображение ошибок PHP, если доступа к php.ini нет?

Создайте в корне сайта файл .user.ini со строками display_errors = On и error_reporting = E_ALL. При PHP как модуле Apache подойдут директивы php_flag в .htaccess.

Почему ini_set('display_errors', '1') не показывает ошибку?

Скорее всего, в файле синтаксическая ошибка: PHP не может разобрать код и не выполняет ни одной строки, включая ini_set(). Проверьте файл командой php -l или включите вывод в php.ini.

Как в PHP показать все ошибки?

Задайте error_reporting(E_ALL) вместе с display_errors = On. В .htaccess вместо константы используйте число -1.

Куда PHP сохраняет error log?

В файл из директивы error_log в php.ini. Если она пустая, сообщения попадают в журнал веб-сервера, например /var/log/apache2/error.log или /var/log/nginx/error.log.

Нужно ли выключать вывод ошибок на рабочем сайте?

Да. На продакшене ставят display_errors = Off и log_errors = On: посетитель не видит пути к файлам и детали базы, а вы читаете всё в логе.