PHP: <? class UserErrorList extends Exception { public $list; function add($message, $code) { $this->list[] = compact('message', 'code'); } } try { $errorList = new UserErrorList; $errorList->add('first', 1); $errorList->add('last', 2); throw $errorList; } catch (UserErrorList $e) { echo '<pre>'; print_r($e->list); } HTML: Array ( [0] => Array ( [message] => first [code] => 1 ) [1] => Array ( [message] => last [code] => 2 ) )
Ti Т.е. если у тебя какой-то из валидаторов формы поднимает исключение, тебе нужно его перехватывать и взамен поднимать другое самодельное исключение, которое способно хранить несколько сообщений? А если другой валидатор тоже сработает, как это разруливать? Не доходит до меня
Я не вижу проблемы о которой Вы говорите. Если у Вас исключения создают непонятки, мб Вы что-то делаете не так.
предложенный тобой вариант ничем не лучше обычного ifelse PHP: $errors = array(); $errors['first']= 1; $errors['last']= 2; if ($errors): echo '<pre>'; print_r($errors); else: echo 'гламурно'; endif;
Ti Пока что я еще ничего не делаю, лишь пытаюсь понять, насколько механизм исключений хорош для решения той или иной проблемы До сегодняшнего дня я искренне считал, что исключения предназначены для обработки фатальных ошибок, возникающих в системе. Т.е. для обработки ситуаций, которые нельзя обработать другими методами. Поскольку некоторые товарищи пытаются здесь представить механизм исключений как некую панацею (и даже сравнивают скорости работы - ну вот объясните мне, какая разница, с какой скоростью будет обработала фатальная ошибка приложения?), я пытаюсь понять, как можно их еще использовать. Psih предложил неплохой пример: обработка формы валидаторами. Соответственно есть набор валидаторов, каждый из которых "пропускает" через себя значение и поднимает исключение, если оно неверно. Вопрос: как на выходе получить и отловить одно исключение, собравшее в себя все ошибки валидации? dark-demon прав, если форма вылетает после первой ошибки - это убожество.
О фатальных ошибках вообще молчу - причины и результаты их ясны. Исключения это прежде всего проблемы предусмотренные разработчиком. Еще раз подчеркиваю, исключения порождает код, который не знает как их обработать. Это их громадное преимущество. Исключения позволяют добиться лучшей инкапсуляции. dark-demon собирает ошибки в массив, а при использовании исключений их можно собрать в одно исключение.
Вообще, принцип исключений - это механизм, с помощью которого можно вылавливать ошибки времени выполнения и обрабатывать их. Тут весь смысл кроется намного глубже, чем просто запись ошибок в лог файл. Это достаточно мощьный механизм, и он позволяет создавать еще и свои исключения. В языке Java существует набор стандартных исключений, например, ввода вывода. В PHP же стандартных нету, но есть возможность создавать свои, что повышает гибкость разработки крупномасштабных проектов на уровне ООП. А фатальные ошибки - это уже соовсем другая история...
AlexGousev хаха =) Да вот интернет подключил =)) решил выбраться на свой любимый форум =) А на работе лазить - шеф матерится...
Исключение != ошибка. Исключение это исключительная ситуация, которую возможно удастся обработать в вышестоящем функционале. Неотловленное исключение == ошибка. Если вместо исключений использовать реткоды, то это приводит к излишней связности снизу-вверх + return занят.
update добавил: PHP: <? /* Любой класс «родитель» может отлавливать исключения «детей». Исключение Exception - родитель всех исключений, им можно отловить ЛЮБОЕ исключение. Имеет значение порядок блоков catch. */ echo '<h2>Наследование в исключениях</h2>'; try { throw new a; } catch (Exception $e) { echo '<h3>Отловили исключение класса ',get_class($e),' при помощи родителя Exception</h3>'; } catch (a $e) { echo '<h3>Этот блок не отработает, т.к. его нужно было разместить раньше</h3>'; } убрал информацию о set_exception_handler, грамотнее глобально отлавливать Exception
update добавил: PHP: <? /* можно отлавливать исключения по интерфейсу */ interface MyExceptionInterface {} class MyException extends Exception implements MyExceptionInterface {} try { throw new MyException; } catch (MyExceptionInterface $e) { echo "Поймали исключение с интефейсом MyExceptionInterface"; }
кусок кода: PHP: <?php if(!empty($_POST['title'])) { $sql = sprintf("SELECT id FROM pr_province WHERE title=%s", cleanQ(ucfirst(strtolower($_POST['title'])))); if($db->numrows($db->query($sql))) { exit(header('Location: admin.php?do=add&add=province&error='.1)); } $sql = sprintf("INSERT INTO pr_province (title) VALUES (%s)", cleanQ(ucfirst(strtolower($_POST['title'])))); $db->query($sql); exit(header('Location: admin.php?do=add&add=province')); ?> как сделать с исключениями проверку: не пустое ли поле title, нет ли такой записи в БД, выполнился ли запрос и тд?
Метод query должен бросать исключение в случае ошибки. PHP: try { if (empty($_POST['title'])) { throw new Exception('Field title is empty'); } //... $db->query('...'); //... } catch (Exception $e) { print 'Error ' . $e->getMessage(); } Правда я не сторонник валидации форм через исключения.
М.б. взглянем на все это с другой стороны? Проверка условными операторами безусловно на много быстрее, но она выполняется при каждом прогоне, а исключения обрабатываются только в случае возникновения ошибки... Я считаю целесообразным следующее: Исключения использовать там, где можно реально сэкономить на куче условных операторов и где исключительные ситуации возникают крайне редко. А проверку условными операторами использовать там, где возникновение исключительной ситуации вполне естественно. Например ввод пользователем неправильного email-адреса вполне естественно и часто имеет место быть... Если честно, до прочтения этой темы я и не думал об использовании исключений при проверке данных, введенных пользователем... А вот передача параметра функции в неправильном формате данных в отлаженном скрипте маловероятно и лишние условные операторы будут миллионы раз проверять правильные значения, тогда как исключение сработает один раз из миллиона прогонов... В этом и разница между условными операторами и обработкой исключений... Условные операторы работают быстро, но прорабатываются всегда. А исключения срабатывают только при возникновении ошибки, но при этом работают на много медленнее. Жду ваших комментариев...
mazzaika Исключения затормаживают само выполнение кода, так что в этом смысле проверка передачи неправильного значения обычным if будет очень сильно быстрее, возьмите проверьте тестом. Где это не очень важно - это при получении формы от пользователя - там удобнее проверить акуратно и выдать исключение при ошибке, красиво всё проставить обратно в форму, чем городить кучу if () { } else { $error = true; $msg = 'some error'; } - тут исключения хорошо помогают.
Ti, красиво. С иключениями начал разбираться совсем недавно и еще нигде не использовал (в PHP), твой пример мне очень помог. В закладки! А крайне редко это насколько? Хочу в своем велосипеде неавторизованным админам отправлять исключение, как думаешь, оправданно?
Каюсь... Не знал... Люди ошибаются очень часто, а машины (при правильной подготовке) на много реже. Вот вам и разница... Если данные вводятся с клавы, либо какие-то данные зависят от деятельности пользователя, то ошибки будут появляться часто... А если проверяется наличие соединения с БД или наличие прав доступа на запись в файл (и т.д. и т.п.), то здесь возникновение ошибки после тестирования и сдачи проекта маловероятно. И уж точно ежедневно повторяться не будет, если не лезть в рабочюю систему руками... А при циклическом обращении к БД (к примеру) скорость работы играет не последнюю роль. Но если исключения в любом случае прорабатываются дольше условных операторов, то все это теряет смысл.
Не корректно заполненная форма это не исключение, а рядовая ошибка. Исключение это когда SQL запрос не может быть выполнен из-за какой-то ошибки, или например когда данные не могут быть записаны в файл, т.к. не хватает прав. Для меня исключение это ошибка, которая, в принципе, не может произойти, если программа функционирует в нормальном режиме.