W3docs

error_reporting()

Функция error_reporting() в PHP: управление уровнями ошибок, настройка отображения и логирования для разработки и продакшена.

Введение

В этой главе рассматривается, как PHP сообщает об ошибках: функция error_reporting(), управляющая какие ошибки PHP генерирует, директивы display_errors и log_errors, управляющие куда эти ошибки отправляются, а также вспомогательные функции для обработки и логирования ошибок. По окончании вы будете знать, как настраивать отчёты об ошибках по-разному для разработки и продакшена, и почему неправильная настройка является одной из самых распространённых ошибок в области безопасности и отладки в PHP.

Почему важна система отчётов об ошибках

PHP работает как гибкий, динамически типизированный язык: многие ошибки, которые остановили бы компиляцию в другом языке, проявляются во время выполнения в виде предупреждений, уведомлений или сообщений об устаревании. Если вы их подавляете, некорректное поведение может незаметно попасть в продакшен. Если же вы показываете их конечным пользователям, вы рискуете раскрыть пути к файлам, SQL-запросы и трассировки стека злоумышленникам.

Правильная система отчётов об ошибках — это верный баланс для каждого окружения:

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

Уровни ошибок и константы

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

КонстантаЗначение
E_ERRORФатальная ошибка времени выполнения; выполнение скрипта прекращается.
E_WARNINGПредупреждение времени выполнения; скрипт продолжает работу.
E_NOTICEУведомление (например, использование неопределённой переменной).
E_DEPRECATEDИспользование функциональности, которая будет удалена в будущей версии PHP.
E_USER_ERROR / E_USER_WARNING / E_USER_NOTICEУровни, которые вы определяете самостоятельно с помощью trigger_error().
E_ALLВсе ошибки, предупреждения и уведомления.

Поскольку это битовые флаги, вы комбинируете их с помощью | (включить), & (маска) и ~ (отрицание):

// All errors EXCEPT notices and deprecation messages
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);

// Only fatal errors and warnings
error_reporting(E_ERROR | E_WARNING);

Примечание о версии: Начиная с PHP 8.0 уровень error_reporting по умолчанию равен E_ALL. E_STRICT был устаревшим в 8.0 и удалён в 8.4, а его уведомления теперь включены в E_ALL, поэтому добавлять его отдельно больше не нужно.

Отчёт против отображения: два разных параметра

Частый источник путаницы состоит в том, что два независимых переключателя определяют, действительно ли вы видите ошибку:

  1. error_reporting() — решает, какие уровни PHP генерирует.
  2. display_errors — решает, выводятся ли сгенерированные ошибки в вывод.

Необходимо включить оба, чтобы увидеть ошибку на экране. В примере ниже генерируется уведомление уровня E_ALL и выводится на экран, потому что оба переключателя включены:

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

echo $undefined;   // Warning: Undefined variable $undefined

Если бы display_errors был выключен, то же уведомление всё равно генерировалось бы (и могло бы быть залогировано), но в выводе страницы ничего не появилось бы.

Основные функции отчётов об ошибках

error_reporting()

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

<?php
$old = error_reporting(E_ALL & ~E_NOTICE);
echo "Now reporting all errors except notices.\n";
echo "Previous level was: " . $old . "\n";

ini_set()

Переопределяет директиву php.ini на время выполнения текущего скрипта. Это эквивалент редактирования php.ini во время выполнения, и именно так переключают display_errors, display_startup_errors и log_errors из кода.

<?php
// Development setup: show everything on screen
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);

Примечание: display_errors не может перехватить фатальные ошибки синтаксического анализа в том же файле, потому что весь файл не компилируется до того, как ini_set() запустится. Для этих случаев задайте директиву непосредственно в php.ini.

set_error_handler()

Регистрирует обратный вызов, который выполняется при каждой (нефатальной) ошибке, позволяя вам заменить поведение PHP по умолчанию — например, преобразовывать предупреждения в исключения или форматировать их как JSON для API. Обратный вызов получает уровень ошибки, сообщение, файл и строку.

<?php
set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline): bool {
    echo "[$errno] $errstr in " . basename($errfile) . " on line $errline\n";
    return true; // true = we handled it; PHP's internal handler is skipped
});

echo $undefined; // routed to our handler instead of the default message

Смотрите set_error_handler() для полной сигнатуры и способов восстановления предыдущего обработчика.

error_log() и trigger_error()

  • error_log() отправляет сообщение в настроенный лог PHP, указанный файл или на адрес электронной почты — но не в вывод страницы. Это безопасный для продакшена способ записи проблем.
  • trigger_error() генерирует ошибку определённую вами (уровни E_USER_*), которая затем проходит через тот же конвейер error_reporting/обработчиков, что и встроенные ошибки.
<?php
// Append a message to a specific log file (message type 3)
error_log("Payment gateway timed out", 3, "/var/log/php_errors.log");

// Raise a user-level warning that your handler / log can pick up
trigger_error("Cache miss for product 42", E_USER_WARNING);

Подробнее в error_log() и trigger_error().

Рекомендуемая конфигурация для каждого окружения

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

<?php
// --- Development ---
error_reporting(E_ALL);
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
<?php
// --- Production ---
error_reporting(E_ALL);          // still GENERATE everything...
ini_set('display_errors', '0');  // ...but never show it to users...
ini_set('log_errors', '1');      // ...log it instead.
ini_set('error_log', '/var/log/php_errors.log');

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

Лучшие практики

  • Никогда не запускайте продакшен с включённым display_errors. Утечка путей и трассировок стека — это риск раскрытия информации.
  • Везде используйте уровень отчётов E_ALL. Отчётность и отображение — разные вещи; подавление уровней лишь скрывает ошибки.
  • Избегайте оператора подавления ошибок @. Он скрывает ошибки в месте вызова и значительно усложняет отладку; вместо этого явно обрабатывайте условие.
  • По возможности перехватывайте ошибки через исключения. Для восстанавливаемых сбоев предпочитайте try/catch обработчикам ошибок. Смотрите PHP Exceptions.
  • Используйте библиотеку логирования в крупных приложениях. Инструменты вроде Monolog предоставляют уровни логов, ротацию и несколько направлений поверх error_log().

Заключение

Система отчётов об ошибках в PHP состоит из трёх слоёв: выбор уровней с помощью error_reporting(), выбор назначения с помощью display_errors / log_errors и, при необходимости, настройка обработки с помощью set_error_handler() и trigger_error(). Настраивайте их осознанно — подробный вывод на экран во время разработки, тихое логирование в продакшене — и вы получите быструю отладку, не раскрывая приложение пользователям или злоумышленникам.

Дополнительное чтение: PHP Error handling · error_get_last() · try…catch.

Практика

Практика
Что можно сказать об отчётах об ошибках в PHP?
Что можно сказать об отчётах об ошибках в PHP?
Was this page helpful?