Просмотр ошибок PHP: отображение и логирование

Раздел: PHP -> Проверка и просмотр ошибок PHP

Основные методы отображения ошибок PHP

Как включить вывод ошибок прямо в скрипте?

Самый простой и быстрый способ увидеть ошибки во время разработки - использовать функции ini_set() и error_reporting() в начале скрипта. Этот метод не требует доступа к серверным конфигурациям и работает для любого сайта, если разрешена переопределение директив.


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

// Пример кода с ошибкой
echo $undefined_variable;
?>

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

Типичные проблемы:

  • Ошибки не отображаются, если в php.ini установлено display_errors = Off, но скрипт может переопределить эту директиву, если разрешено (обычно разрешено).
  • Некоторые хосты запрещают переопределение через ini_set() - тогда нужно использовать другие методы.
  • Уровень E_ALL включает все типы ошибок, включая уведомления и предупреждения. Можно использовать E_ALL & ~E_NOTICE & ~E_STRICT для исключения несущественных сообщений.

Как настроить показ ошибок через файл .htaccess?

Если сервер работает под управлением Apache и доступен файл .htaccess, можно задать директивы PHP прямо в нем. Это полезно, когда нет доступа к php.ini.


php_flag display_errors on
php_value error_reporting 32767  # E_ALL

Цифра 32767 соответствует E_ALL в PHP 5.x; для PHP 7+ она равна 32767, но лучше использовать константу E_ALL (если сервер её поддерживает).

Проблемы:

  • Не все хостинги разрешают переопределение этих директив через .htaccess.
  • Синтаксис php_value и php_flag может отличаться в зависимости от версии Apache и PHP.
  • Если в .htaccess уже есть другие настройки, возможен конфликт.

Как изменить глобальные настройки обработки ошибок через php.ini?

Редактирование основного конфигурационного файла PHP - самый надёжный способ. Подходит для администраторов сервера.


; Включить отображение ошибок
display_errors = On
; Уровень ошибок
error_reporting = E_ALL
; Путь к лог-файлу
error_log = /var/log/php_errors.log

После изменения нужно перезагрузить веб-сервер (Apache, Nginx).

Проблемы:

  • Нет доступа к php.ini на общем хостинге.
  • Ошибки могут быть скрыты, если display_errors выключен, но error_log включен - тогда они пишутся только в лог.

Как настроить ошибки для конкретной директории через .user.ini?

Начиная с PHP 5.3.0, можно использовать файл .user.ini в корне директории. Это аналог .htaccess, но для CGI/FastCGI.


display_errors = On
error_reporting = E_ALL

Изменения применяются автоматически, перезагрузка сервера не требуется.

Проблемы:

  • Работает только при использовании CGI/FastCGI, не для модуля mod_php.
  • На некоторых хостингах может быть отключено.

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

При выполнении PHP-скрипта в консоли можно передать параметры через -d.


php -d display_errors=1 -d error_reporting=E_ALL script.php

Это удобно для разовой отладки, не меняя конфигурационные файлы.

Проблемы:

  • Не применимо для веб-запросов.
  • Константу E_ALL нужно указывать в числовом виде, если система не распознает строковое значение.

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

Функция error_get_last() возвращает массив с информацией о последней произошедшей ошибке. Это полезно для записи в лог или отображения в специальном блоке.


<?php
// Производим действие, которое может вызвать ошибку
$result = file_get_contents('nonexistent.txt');

$error = error_get_last();
if ($error) {
    echo 'Тип: ' . $error['type'] . "\n";
    echo 'Сообщение: ' . $error['message'] . "\n";
    echo 'Файл: ' . $error['file'] . "\n";
    echo 'Строка: ' . $error['line'] . "\n";
}
?>

Проблемы:

  • error_get_last() возвращает только последнюю ошибку, предыдущие теряются.
  • Не работает для фатальных ошибок (E_ERROR, parse error), так как скрипт прерывается до вызова функции.

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

С помощью set_error_handler() и set_exception_handler() можно перехватывать все ошибки и исключения, направляя их в свой код (например, для красивого вывода или логирования).


<?php
// Функция-обработчик ошибок
function myErrorHandler($errno, $errstr, $errfile, $errline) {
    echo "<b>Ошибка:</b> [$errno] $errstr в файле $errfile на строке $errline\n";
    return true; // не запускать стандартный обработчик
}

set_error_handler('myErrorHandler');

// Пример
trigger_error('Произошло предупреждение', E_USER_WARNING);
?>

Проблемы:

  • Стандартный обработчик не перехватывает фатальные ошибки (E_ERROR, E_PARSE) - для них нужен register_shutdown_function() или использование symfony/error-handler.
  • Если функция обработчика сама вызовет ошибку, это может привести к рекурсии.

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

Библиотеки вроде filp/whoops предоставляют красивое отображение ошибок с трассировкой стека и контекстом. Установка через Composer:


composer require filp/whoops

Затем в скрипте:


<?php
require 'vendor/autoload.php';

$whoops = new \Whoops\Run;
$whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);
$whoops->register();

// Ошибка для демонстрации
echo 1/0;
?>

Результат - страница с подробной информацией об ошибке.

Проблемы:

  • Требует установки через Composer и может быть избыточно для простых проектов.
  • Не все хосты поддерживают сторонние библиотеки.

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

Ниже приведены более детальные примеры с выводом результатов, демонстрирующие различные аспекты управления ошибками.

1. Настройка вывода ошибок и логирования с разными уровнями

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

Пример

<?php
// Включаем отображение только фатальных ошибок
ini_set('display_errors', '1');
error_reporting(E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR);

// Логируем всё остальное
ini_set('log_errors', '1');
ini_set('error_log', '/tmp/php_errors.log');

// Генерируем разные ошибки
echo $undefined; // уведомление - будет в лог, но не на экране
trigger_error('Пользовательское предупреждение', E_USER_WARNING); // в лог
function test() { echo 1/0; } // деление на ноль - предупреждение (в лог)
test();
?>
(На экране:
Warning: Division by zero in /path/file.php on line 13
) 
В файле /tmp/php_errors.log будут все три сообщения.

2. Использование error_get_last для фиксации ошибок доступа к файлам

Пример

<?php
$file = @file_get_contents('missing.txt');
$lastError = error_get_last();
if ($lastError !== null) {
    echo 'Последняя ошибка: ' . $lastError['message'];
}
// Если несколько ошибок, error_get_last вернет последнюю
// Попробуем два вызова
@file_get_contents('a.txt');
@file_get_contents('b.txt');
$lastError = error_get_last();
echo '; последняя: ' . $lastError['message'];
?>
Последняя ошибка: file_get_contents(missing.txt): Failed to open stream: No such file or directory; последняя: file_get_contents(b.txt): Failed to open stream: No such file or directory

3. Пользовательский обработчик ошибок с классификацией и записью в БД

Пример

<?php
function dbErrorHandler($errno, $errstr, $errfile, $errline) {
    // Классификация
    $type = 'Unknown';
    switch ($errno) {
        case E_WARNING: $type = 'Warning'; break;
        case E_NOTICE: $type = 'Notice'; break;
        case E_USER_ERROR: $type = 'User Error'; break;
    }
    // Запись в БД (пример)
    $msg = sprintf('[%s] %s in %s:%d', $type, $errstr, $errfile, $errline);
    // file_put_contents('errors.log', $msg.PHP_EOL, FILE_APPEND);
    echo "<div class='error'>$msg</div>";
    return true;
}

set_error_handler('dbErrorHandler');

trigger_error('Проверка работы обработчика', E_USER_NOTICE);
?>
<div class='error'>[Notice] Проверка работы обработчика in /path/file.php:18</div>

4. Перехват фатальных ошибок через register_shutdown_function

Пример

<?php
function fatalHandler() {
    $error = error_get_last();
    if ($error !== null && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
        echo 'Фатальная ошибка: ' . $error['message'] . ' в файле ' . $error['file'];
    }
}

register_shutdown_function('fatalHandler');

// Вызов несуществующей функции
undefinedFunction();
?>
Фатальная ошибка: Call to undefined function undefinedFunction() in /path/file.php:11

5. Комбинированный подход: вывод ошибок в режиме разработки, скрытие в продакшене

Пример

<?php
// Определяем окружение
$env = getenv('APP_ENV') ?: 'production';

if ($env === 'dev' || $env === 'development') {
    ini_set('display_errors', '1');
    error_reporting(E_ALL);
    ini_set('log_errors', '1');
} else {
    ini_set('display_errors', '0');
    error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED);
    ini_set('log_errors', '1');
    ini_set('error_log', '/var/log/app_errors.log');
}
?>

Такой подход позволяет безопасно переключаться между режимами без изменения кода.

6. Использование Xdebug для расширенной отладки

Пример

// Установка Xdebug (через pecl или apt)
// В php.ini:
xdebug.mode = develop,debug
xdebug.start_with_request = yes
xdebug.client_host = 127.0.0.1
xdebug.client_port = 9003

Xdebug предоставляет цветной вывод ошибок с трассировкой стека, но требует настройки IDE.

Просмотр ошибок PHP - comments

En
посмотреть ошибки php (php)