Настройка показа ошибок в 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 его отключают.