Система каскадной обработки исключений

May 4, 2010 by admin Комментировать »

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

Поэтому одним из наиболее ожидаемых нововведений в РНР 5 можно без пре­уменьшения назвать новую схему обработки исключений, реализованную в конст­рукции try/catch и операторе throw.

Рассмотрим пример использования конструкции, а затем обсудим те преимуще­ства, которые дает такой подход.

<?php try {

$fp = @fopen("file.txt’. *w"): if (!$fp) {

throw new Exception ( ‘ Невозможно открыть файл 1 ‘) ,-

}

// Запись данных в файл fclose(Sfp);

}

catch (Exception $exception) {

echo ‘Ошибка в строке ‘, $exception->getLine(); echo $exception->getMessage();

// Выводит "Невозможно открыть фги1л"

}

?>

Итак, если программе не удастся открыть файл с именем f ile. txt, то благода­ря оператору подавления вывода сообщений об ошибке никаких сообщений выве­дено не будет. Однако в этом случае произойдет создание и "выброс" экземпляра встроенного класса исключения (Exception).

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

Код, который следует после инструкции throw, после возникновения исключе­ния выполняться не будет. Поток выполнения переходит к блоку catch, после чего выполняется код, который следует за ним.

В конструкции try/catch можно использовать несколько блоков catch, обра­батывающих исключения различных типов, например, ошибок работы с базой данных, системных ошибок, ошибок работы с файловой системой и т.п. Для этих типов исключений имеет смысл создать специальные классы-наследники от встро­енного класса Exception, который выглядит так.

<?php

class Exception {

protected Snessage = ‘Unknown exception’;

// сообщение protected $code =0; // код исключения

protected $file; // имя файла

protected $line; // строка прозтраммы

function _construct($message = null, $code = 0);

final function getMessage(); final function getCode(); final function getFileO; final function getLineO;

final function getTraceO; // массив обратной трассировки

final function getTraceAsString();

// строковое представление // обратной трассировки

function _toStringO; // строковое представление

// исключения

}

?>

О назначении свойств и методов данного класса догадаться нетрудно. Метод

_toString () уже обсуждался в предыдущей главе. Он может быть перегружен

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

Сообщение обратной трассировки (по английски traceback) обычно содержит список функций из стека вызовов на момент возникновения исключения с указа­нием строк, на которых была вызвана каждая функция стека.

Таким образом найти и исправить ошибку становится гораздо проще. Рассмот­рим пример.

<?php

function flO {

echo ‘Начало fl()<br>*

throw new Exception(‘Тестовая ошибка’); echo ‘Конец f1()<br>’;

)

function f2() {

echo •Начало f2()<br>’; f 1 () ;

echo ‘Конец f2()<br>’i

}

function f3() {

echo ‘Начгшо f3()<br> f 2 <) ;

echo ‘Конец f3()<br>’;

}

echo • Начало основной про17рёишы<Ьг> ‘ ; f 3 () ;

echo ?Конец основной программы’;

?>

В результате выполнения данной программы мы получим следующий вывод.

Fatal error: Uncaught exception ‘Exception’ with message ‘Тестовая ошибка’

in f:\site\Apache\htdocs\test.php: 4 Stack trace: #0 f:\site\Apache\htdocs\test.php(4): fl() #1 f:\site\Apache\htdocs\test.php(10): f1() #2 f:\site\Apache\htdocs\test.php(16): f2() #3 f:\site\Apache\htdocs\test.php(20): f3() #4 {main} thrown in f:\site\Apache\htdocs\ test.php on line 4

Разберем это сообщение об ошибке подробнее. Итак, мы сгенерировали тестовую ошибку в теле функции f 1 () на четвертой строке, и работа программы была оста­новлена. Далее стандартный обработчик вывел стек функций: f 1 () была вызвана из функции f 2 () на строке 10, f 2 () — из f 3 () на строке 16, а f 3 () — из основной программы на строке 20.

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

function f2() {

echo ‘Начало f2()<br>’; try {

f 1 () ;

)

catch (Exception $exception) { echo ‘Возникло исключение!’; throw new Exception($exception->message);

}

echo •Конец f2()<br>’;

}

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

Новая система обработки исключений РНР 5 позволяет также создавать свои собственные типы исключений путем наследования от стандартного класса Excep­tion. Например:

<?php

// DBException.php

class DataBaseException extends Exception{

public function _construct($inessage, $code – 0) {

// Здесь мотут производиться дополнительные действия parent::_construct($inessage, $code);

}

public function _toString() {

return "[{$this->code}]: {$this->message}\n";

>

}

?>

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

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

<?php

require_once "DBException.php"; try {

// Потенциально опасные действия

}

catch (DataBaseException $exception) { // Обработка ошибки работы с БД

}

catch (Exception $exception) {

// Обработка всех остальных ошибок

}

?>

Оставить комментарий

микросхемы мощности Устройство импульсов питания пример приемника провода витков генератора выходе напряжение напряжения нагрузки радоэлектроника работы сигнал сигнала сигналов управления сопротивление усилитель усилителя усиления устройства схема теория транзистора транзисторов частоты