3.10.1 Серьезность "несерьезных" ошибок

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

Для примера рассмотрим сообщение класса E_WARNING, возникающее при ошибке открытия файла. Является ли оно фатальным, и возможно ли дальнейшее выполнение программы при его возникновении без каких-либо ветвлений? Однозначного ответа на этот вопрос дать нельзя.

Вот две крайние ситуации.

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

● Невозможность открытия файла практически ни на что не влияет. К примеру, программа может записывать в этот файл информацию о том, когда она была запущена. Или даже более простой пример: скрипт просто проверяет, существует ли нужный файл, а если его нет, то создает новый пустой.

Рассмотрим теперь самое "слабое" сообщение, класса E_NOTICE, которое генерируется РНР, например, при использовании неинициализированной переменной. Часто такие ошибки считают настолько незначительными, что даже отключают реакцию на них в файле php.ini (error_reporting=E_ALL~E_NOTICE). Более того, именно такое значение error_reporting выставляется по умолчанию в дистрибутиве PHP.

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

Предположим, вы исполняете SQL-запрос для добавления новой записи в таблицу MySQL:

INSERT INTO table (id, parent_id, text)

VALUES (NULL, '$pid', 'Have you ever had a dream, that you were so sure was real?')

В переменной $pid хранится некоторый идентификатор, который должен быть обязательно числовым. Если эта переменная окажется неинициализированной (например, где-то в программе выше произошла опечатка), будет сгенерирована ошибка E_NOTICE, а вместо $pid подставится пустая строка. SQL-запрос же все равно останется синтаксически корректным. В результате в базе данных появится запись с полем parent_id, равным нулю (пустая строка '' без всяких предупреждений трактуется MySQL как 0). Это значение может быть недопустимым для поля parent_id (например, если оно является внешним ключом для таблицы table, т. е. указывает на другую "родительскую" запись с определенным ID). А раз значение недопустимо, то целостность базы данных нарушена, и это в дальнейшем вполне может привести к серьезным последствиям (заранее непредсказуемым) в других частях скрипта, причем об их связи с одним-единственным E_NOTICE, сгенерированным ранее, останется только догадываться.

● Теперь о том, когда E_NOTICE может быть безвредной. Вот пример кода:

cinput type="text" name "field"

value="<?=htmlspecialchars($_REQUEST['field'])?>">

Очевидно, что если ячейка $_REQUEST['field'] не была инициализирована (например, скрипт вызван путем набора его адреса в браузере и не принимает никаких входных данных), элемент формы должен быть пуст. Подобная ситуация настолько широко распространена, что обычно ставят @ перед обращением к элементу массива, или даже перед htmlspecialchars(). В этом случае сообщение будет точно подавлено.

3.10.2 Преобразование ошибок в исключения

Мы приходим к выводу, что ошибку любого уровня можно трактовать как "серьезную" (за исключением ситуации, когда перед выражением явно указан оператор @, подавляющий вывод всех ошибок. Для обработки же серьезных ошибок в РНР имеется прекрасное средство — исключения.

Пример. Решение, которое мы здесь рассмотрим, — библиотека для автоматического преобразования всех перехватываемых ошибок РНР (вроде E_WARNING, E_NOTICE и т. д.) в объекты-исключения одноименных классов. Таким образом, если программа не сможет, например, открыть какой-то файл, теперь будет сгенерировано исключение, которое можно перехватить в соответствующем участке программы. Листинг 3.11 иллюстрирует сказанное.

Листинг 3.11. Файл w2e_simple.php

<?php ## Преобразование ошибок в исключения.

require_once "lib/config.php";

require_once "PHP/Exceptionizer.php";

// Для большей наглядности поместим основной проверочный код в функцию.

suffer();

// Убеждаемся, что перехват действительно был отключен.

echo "<b>Дальше должно идти обычное сообщение PHP.</b>";

fopen("fork", "r");

function suffer() {

 // Создаем новый объект-преобразователь. Начиная с этого момента

 // и до уничтожения переменной $w2e все перехватываемые ошибки

 // превращаются в одноименные исключения.

 $w2e = new PHP_Exceptionizer(E_ALL);

 try {

 // Открываем несуществующий файл. Здесь будет ошибка E_WARNING.

 fopen("spoon", "r");

 } catch (E_WARNING $e) {

 // Перехватываем исключение класса E_WARNING.

 echo "<pre><b>Перехвачена ошибка!</b>\n", $e, "</pre>";

 }

 // В конце можно явно удалить преобразователь командой:

 // unset($w2e);

 // Но можно этого и не делать - переменная и так удалится при

 // выходе из функции (при этом вызовется деструктор объекта $w2e,

 // отключающий слежение за ошибками).

}

?>

Обратите внимание на заголовок catch-блока. Он может поначалу ввести в заблуждение: ведь перехватывать можно только объекты-исключения, указывая имя класса, но никак не числовое значение (E_WARNING — вообще говоря, константа РНР, числовое значение которой равно 2 — можете убедиться в этом, запустив оператор echo E_WARNING). Тем не менее ошибки нет: E_WARNING — это одновременно и имя класса, определяемого в библиотеке PHP_Exceptionizer.

Заметьте также, что для ограничения области работы перехватчика используется уже знакомая нам идеология: "выделение ресурса есть инициализация". А именно в том месте, с которого необходимо начать преобразование, мы помещаем оператор создания нового объекта PHP_Exceptionizer и запоминаем последний в переменной, а там, где преобразование следует закончить, просто уничтожаем объект-перехватчик (явно или, как в примере, неявно, при выходе из функции).



Информация о работе «Обработка ошибок в коде программ РНР»
Раздел: Информатика, программирование
Количество знаков с пробелами: 79083
Количество таблиц: 1
Количество изображений: 0

Похожие работы

Скачать
85123
2
8

... от необходимости самим создавать соответствующие программы. Присутствует в ASP и PHP, отсутствует в XML. Создание серверных сценариев. Основа любого языка для создания динамических сайтов. Присутствует в ASP и PHP, отсутствует в XML. Описание данных. Важная функция, позволяющая представлять данные в едином формате, единым способом записи. Отсутствует в ASP и PHP, присутствует в XML. Наличие ...

Скачать
70189
1
170

... Apache на русском языке: Если открылась начальная страница, значит Apache установлен правильно. ● Перейдите в окно Web-сервера Apache с помощью Панели задач операционной системы Windows и завершите работу сервера с помощью кнопки [X] в правом верхнем углу окна. 1.3. Установка PHP Загрузить дистрибутивов PHP можно с официальной страницы http://www.php.net/downloads.php из секции Windows ...

Скачать
184575
9
11

... 20% от общего товарооборота, соответственно окупаемость магазина произойдет за более длинный промежуток времени, нежели чем при полном ассортименте. Получение дополнительной прибыли электронному магазину по продаже программного обеспечения, компакт дисков и dvd дисков на основании приведенных выше затрат ожидается уже с третьего - четвертого месяца, что является достаточно хорошим экономическим ...

Скачать
111078
12
21

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

0 комментариев


Наверх