Учебное пособие: Обработка ошибок в коде программ РНР
echo "</div>";
}
// Регистрируем ее для всех типов ошибок.
set_error_handler("myErrorHandler", E_ALL);
// Вызываем функцию для несуществующего файла, чтобы
// сгенерировать предупреждение, которое будет перехвачено.
filemtime("spoon");
?>
Теперь при возникновении любой ошибки или даже предупреждения в программе будет вызвана функция myErrorHandier(). Ее аргументы получат значения, соответственно, номера ошибки, текста ошибки, имени файла и номера строки, в которой было сгенерировано сообщение.
К сожалению, не все типы ошибок могут быть перехвачены таким образом. Например, ошибки трансляции во внутреннее представление E_PARSE, а также E_ERROR немедленно завершают работу программы. Вызовы функции die()также не перехватываются.
Назначить функцию реакции на E_PARSE и E_ERRORвсе же можно. Дело в том, что перехватчик выходного потока скрипта, устанавливаемый функцией ob__start(), обязательно вызывается при завершении работы программы, в том числе в случае фатальной ошибки. Конечно, ему не передается сообщение об ошибке и ее код; он должен сам получить эти данные из "хвоста" выходного потока (например, используя функции для работы с регулярными выражениями).
В случае если пользовательский обработчик возвращает значение false (и только его!), считается, что ошибка не была обработана, и управление передается стандартному обработчику РНР (обычно он выводит текст ошибки в браузер). Все остальные возвращаемые значения (включая даже null или, что то же самое, в случае, если оператора return вообще нет), приводят к подавлению запуска стандартной процедуры обработки ошибок.
2.2 ФУНКЦИЯrestore_error_handler()
void restore_error_handler()
Когда вызывается функция set_error_handler(), предыдущее имя пользовательской функции запоминается в специальном внутреннем стеке РНР. Чтобы извлечь это имя и тут же его установить в качестве обработчика, применяется функция restore_error_handler().Пример:
// Регистрируем обработчик для всех типов ошибок.
set_error_handler("myErrorHandler", E_ALL);
// Включаемподозрительныйфайл.
include "suspicious_file.php";
// Восстанавливаем предыдущий обработчик.
restore_error_handler();
Необходимо следить, чтобы количество вызовов restore_error_handler() было в точности равно числу вызовов set_error_handler().Нельзя восстановить то, чего нет.
2.3 ПРОБЛЕМЫ С ОПЕРАТОРОМ @
Пользовательская функция перехвата ошибок вызывается вне зависимости от того, был ли использован оператор подавления ошибок в момент генерации предупреждения. Это очень неудобно: поставив оператор @ перед вызовом filemtime(), мы увидим, что результат работы скрипта нисколько не изменился: текст предупреждения по-прежнему выводится в браузер.
Для того чтобы решить проблему, воспользуемся полезным свойством оператора @: на время своего выполнения он устанавливает error_reporting, равным нулю. Значит, мы можем определить, был ли вызван оператор @ в момент "срабатывания" обработчика, по нулевому значению функции error_reporting() (при вызове без параметров она возвращает текущий уровень ошибок) — листинг 2.3.
Листинг 2.3. Файл handler.php
<?php ## Перехват ошибок и предупреждений.
// Определяем новую функцию-обработчик.
functionmyErrorHandler($errno, $msg, $file, $line) {
// Если используется @, ничего не делать.
if (error_reporting() == 0) return;