Настройка показа ошибок в PHP: лучшие практики и примеры

Раздел: Основы PHP -> Обработка ошибок

Настройка отображения ошибок PHP

Наиболее эффективным решением для контроля отображения ошибок PHP является комбинация директив error_reporting и display_errors. В рабочем проекте эти параметры задаются в конфигурационном файле php.ini или на уровне веб-сервера, а в процессе разработки - динамически через функции ini_set() и error_reporting().

Рекомендуемая настройка для разработки:


// Включить отображение всех ошибок
error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
  

Этот код необходимо разместить в самом начале скрипта (до любого вывода). Директива display_startup_errors отвечает за ошибки, возникающие при старте PHP (например, в php.ini), их также полезно видеть на этапе разработки.

Как настроить ошибки через php.ini для всех скриптов?

В файле php.ini нужно изменить или добавить строки:


error_reporting = E_ALL
display_errors = On
display_startup_errors = On
  

После изменений требуется перезапустить веб-сервер. Этот способ применяется, когда нужно унифицировать поведение для всего проекта.

Как включить ошибки только для конкретной директории через .htaccess?

На серверах Apache можно использовать файл .htaccess:


php_value error_reporting E_ALL
php_flag display_errors on
php_flag display_startup_errors on
  

Важно:

Эти директивы работают только если Apache mod_php включен и разрешена переопределение настроек (AllowOverride Options). В противном случае сервер вернёт ошибку 500.

Как настроить отображение ошибок для конкретного скрипта без изменения глобальных файлов?

Используйте ini_set() и error_reporting() внутри скрипта, как показано в основном решении. Этот вариант удобен для временных отладок или в средах, где нет доступа к php.ini.

Как скрыть ошибки на production, но сохранить их в лог?

На боевом сервере следует отключить вывод ошибок, но логировать их:


ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
error_reporting(E_ALL); // или E_ALL & ~E_NOTICE и т.п.
ini_set('log_errors', 1);
ini_set('error_log', '/path/to/php-errors.log');
  

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

Как переопределить стандартное поведение обработки ошибок с помощью пользовательского обработчика?

Функция set_error_handler() позволяет перехватывать ошибки и выполнять собственные действия:


function myErrorHandler($severity, $message, $file, $line) {
    throw new ErrorException($message, 0, $severity, $file, $line);
}
set_error_handler('myErrorHandler');
  

Теперь все ошибки превращаются в исключения, которые можно ловить блоком try...catch. Этот подход удобен для централизованной обработки.

Типичные проблемы и их решения

  • Ошибка «Headers already sent» - возникает, если display_errors включён и скрипт выводит данные до вызова ini_set(). Решение: размещать настройки до любого вывода (включая пробелы перед <?php).
  • Настройки .htaccess не работают - проверьте, разрешена ли директива php_value на сервере (часто отключена в целях безопасности). Используйте ini_set() в скрипте или измените php.ini.
  • На production показываются ошибки - убедитесь, что display_errors установлен в 0, а log_errors в 1. Проверьте, не переопределяется ли значение в .htaccess или в коде.
  • При использовании set_error_handler() не перехватываются фатальные ошибки (E_ERROR) - пользовательский обработчик не срабатывает для фатальных ошибок, для их перехвата используют register_shutdown_function() или error_get_last().

Расширенные примеры настройки отображения ошибок PHP

Пример 1. Разные уровни error_reporting

В PHP существует несколько уровней ошибок. Комбинируя их, можно гибко фильтровать отображаемые сообщения.

Пример

// Показывать только фатальные ошибки и предупреждения
error_reporting(E_ERROR | E_WARNING | E_PARSE);
ini_set('display_errors', 1);

// Вызов несуществующей функции
foo(); // Фатальная ошибка: Uncaught Error: Call to undefined function foo()

// Обращение к несуществующей переменной
echo $undefinedVar; // Warning: Undefined variable $undefinedVar
Warning: Undefined variable $undefinedVar in /path/to/file.php on line 8
Fatal error: Uncaught Error: Call to undefined function foo() in /path/to/file.php:5
Stack trace:
#0 {main}
  thrown in /path/to/file.php on line 5

Пояснение:

Уровень E_ERROR - фатальные, E_WARNING - предупреждения, E_PARSE - синтаксические ошибки. Комбинация через побитовое ИЛИ.

Пример 2. Включение ошибок через .htaccess с проверкой работоспособности

Пример

# .htaccess
php_value error_reporting E_ALL & ~E_DEPRECATED & ~E_STRICT
php_flag display_errors on

Этот код покажет все ошибки, кроме уведомлений об устаревшем коде и строгих стандартов. Типичная проблема: если .htaccess неправильно синтаксически оформлен, Apache выдаст 500 Internal Server Error. Решение - проверять синтаксис с помощью apachectl configtest.

Пример 3. Логирование ошибок с разными файлами

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

Пример

function advancedErrorHandler($severity, $message, $file, $line) {
    $logDir = '/var/log/php/';
    $logFile = ($severity & (E_ERROR | E_PARSE)) ? $logDir . 'fatal.log' : $logDir . 'warning.log';
    $date = date('Y-m-d H:i:s');
    file_put_contents($logFile, "[$date] [$severity] $message in $file:$line\n", FILE_APPEND);
    // Не отображаем ошибки пользователю
    return true;
}
set_error_handler('advancedErrorHandler');

// Проверка
trigger_error('Это предупреждение', E_USER_WARNING);
trigger_error('Это ошибка пользователя', E_USER_ERROR);
(в файле /var/log/php/warning.log)
[2025-03-30 12:00:00] [512] Это предупреждение in /path/to/file.php:13
(в файле /var/log/php/fatal.log)
[2025-03-30 12:00:00] [256] Это ошибка пользователя in /path/to/file.php:14

Пример 4. Использование error_get_last() для фатальных ошибок

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

Пример

register_shutdown_function(function() {
    $lastError = error_get_last();
    if ($lastError !== null && in_array($lastError['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
        // Отправить уведомление разработчику
        error_log("FATAL: {$lastError['message']} in {$lastError['file']}:{$lastError['line']}");
        // Вывести дружественное сообщение пользователю
        echo 'Произошла критическая ошибка. Команда уже уведомлена.';
    }
});

// Вызов несуществующего метода
$obj = new stdClass();
$obj->nonExistentMethod(); // Фатальная ошибка
Произошла критическая ошибка. Команда уже уведомлена.
(в логе) FATAL: Call to undefined method stdClass::nonExistentMethod() in /path/to/file.php:11

Пример 5. Комбинирование с отладчиком Xdebug

Если Xdebug установлен, он может переопределять вывод ошибок. Чтобы видеть более информативные трассировки, настройте:

Пример

; php.ini
xdebug.mode = develop
xdebug.start_with_request = yes

Тогда при включённом display_errors ошибки будут показываться с цветной подсветкой и расширенным стеком. Однако помните, что Xdebug снижает производительность, поэтому для production его отключают.

Настройка отображения ошибок PHP - comments

En
Reporting php (php)