Прочитал http://habrahabr.ru/blogs/php/30829/ , решил ее у себя использовать. Сделал set_error_handler('_aero_custom_error_handler', E_ALL & ~ E_NOTICE); // Это мой стандартный вариант показа ошибок пока что - все, кроме нотайсов. Но получается так, что она не обрабатывает не пойманные исключения. Какие еще есть варианты для оформления ошибок да исключений?
PHP: <? function redirect_on_except($e) { ob_end_clean(); header('Location: ' . ERROR_PAGE); $error_log_file = LOG_PATH . 'phpexp.log'; $error_string = "{$e->getCode()}: Except text: {$e->getMessage()} in file: {$e->getFile()} line: {$e->getLine()} trace: {$e->getTraceAsString()} "; if(file_exists($error_log_file)) { $errors = file_get_contents($error_log_file); if (!preg_match($error_string , $errors)) { error_log($error_string, 3, $error_log_file); } } else { error_log($error_string, 3, $error_log_file); } exit; } set_exception_handler("redirect_on_except");
еще можешь в set_error_handler генерировать исключение, и оно будет отлавливаться в set_exception_handler. Но учти вообще, что исключения тормозная штука... Например, некотрые личности оперируют ими для реализации определенной логики работы - я противник этого, лучше реализовать чтото попроще, например, возвращать FALSE, а не генерировать исключение, чтобы потом перехватить его, узнать тип или сразу "определенно" перехватить и выполнить какойто код...
да я в курсе, что они медленные. Это ж дебаг-онли, ессно форму контактную я не проверяю исключениями.
у меня повсюду в классах исключения понатыканы. наприммер в store() проверится, есть ли имя у объекта, есть ли тип, путь и все остальное. если нет будет исключение, во всех методах, которые он вызывает, такая же петрушка. Везде куча исключений. И я нашел удивительно легкий способ как сообщать об ошибках пользователю, используя свои же исключения. Раньше то это для меня была проблема. Теперь все что в контролерах происходит я помещаю в трай-кэтч. например если раньше нажимал на кнопку "сторе", то в контролере было PHP: <?php function OnStore(){ $page= $this->m; $page->obj()->store(); TOR::db()->commit(); header на просмотр; } И тут проблема, как всегда, а что же произойдет если внутри сторе() выплывет исключение? как его показать пользователю? редиректить куда- то не катит, потому что все что пользователь ввел на форме, пропадет, если даже он нажмет на кнопку "назад", все равно пропадет. А он может быть десять минут эту форму заполнял. Это приводит всех в ярость. Красивый вывод ошибки это не сгладит. Теперь я делаю так. ничего не меняю, что не может не радовать, только небольшая доделочка: PHP: <?php function OnStore(){ $page= $this->m; try{ $page->obj()->store(); TOR::db()->commit(); header на просмотр; } catch(Exception $e){ $page->error= $e; $view= new PageView($page); $view->show(); die; } } Это очень универсальный способ, чтобы обработать любую мыслимую и немыслимую ошибку пользователя. Особенно радует, что ничего не надо переделывать. Только добавил в модель Page поле $error и во вьюшке PageView в том месте, где начинается вывод содержания страницы, проверку, если $model->error, выводи вьюшку Exceptiona. Это все доделки. Тексты сообщений тоже уже есть в $message эксепшина. После этого все страницы заработали по новому, потому что они все пронаследованы от Page, а их вьюшки от PageView. Выглядит это вот так. сначала страница без ошибки, потом с ошибкой. как видно весь пользовательский ввод не потерялся. Для пользака очень удобно. почитал где ошибся, поправил и повторил. это им понравится. не очень красиво, потому что в дебуге, но смысл я думаю хорошо понятен.
alexey_baranov а что нельзя сделать, чтобы $page->obj()->store(); возвращал массив ошибок? намного все быстрее будет работать и проще как по мне...
а как ты сохраняешь значение поле с input-file после перезагрузки страницы? х3, у меня пока все ошибки внутри одного класса обрабатываются. То есть есть класс ManagerManufacturers - управление производителями. Если пользователь ввел что-то неверное, то внутри этого класса я и показываю ошишки простой проверкой if($this->errors) {показать ошибки} else {залить значения в БД}.
Не эксепшн- есть эксепшн. для того его и придумали, чтобы ифы больше не городить. при обработке ошибок try-catch и эксепшины ничто не заменит. насчет скорости, я принадлежу к той категории людей, которая считает, что людское время дороже машинного. конечно, если речь не идет о каких- нибудь расчетах на супердорогих суперкомпьютерах.
у меня контролер файлового поля сохраняет новые файлы в специальный отстойник на серваке. при перезагрузках страницы они второй раз не отправляются. выглядит это вот так. думаю на этой картинке все понятно. а на предыдущей картинке я сначала вызвал ошибку, а потом только увидел что забыл про файлы, ну и выбрал их, чтобы не выглядело как будто файлы после ошибки отцепились. а ты внимательный . то есть если пользак долго заполнял форму и к своему неудовольствию обнаружил, что все равно заполнил ее неправильно, то при моем методе на форме сохраняются и все тексты, и все файлы.
alexey_baranov я имею в виду что исключения придумали для того, чтобы отлавливать ошибки которые программисту в голову прийти не могут - исключительные ошибки... Если бы мы знали все ошибки которые могли произойти в приложении, то все программы бы были без ошибок. Вот для этого и придуманы исключения, чтобы отлавливать эти как бы скрытые от программиста ошибки - исключительные ситуации, которых теоретически возникнуть как бы не должно... В твоем примере ты передаешь ошибку чере message объекта исключения, вызывая исключение, которое и так можно предвидеть - неправильный ввод пользователя. Я же предлагаю делать тоже самое только с помощью массива. Если его размер ноль - то ошибок нету. Иначе циклом все вывел, и прекрасно при этом остаются на форме уже заполненные поля - это совсем другое... Я тоже раньше делал целую структуру классов исключений, продумывал ее, но когда посмотрел как всё тупит, то выкинул это из головы...
Из последних. К примеру, я забыл где- то в коде указать почтовый ящик, куда надо отправить почту. это произошло просто по запарке. чтобы такие ситуации контролировать, всегда в таких случаях делаю проверку внутри класса PHP: <?php if (!$this->to) throw new MailException(бла бла бла укажите адрес) отправляю почту а ты как в этой ситуации поступаешь?
Тут исключительная ситуация, потому что в класс не передали адрес отправки. А вот если бы юзер не указал адрес в форме, то это была бы контролируемая ошибка, которую можно отследить на этапе валидации формы.
Я смысла всего этого не понимаю. вот объясни мне, если я точно знаю что это проверит почтовый класс, зачем мне это- же самое еще раз проверять в форме? есть ли в этом какой- то смысл? И второй вопрос что делать, если логика работы класса изменится. к примеру, адрес не задали- значит отправляй на адрес по умолчинию. Я конечно поменяю реализацию класса, и потом еще должен буду поменять и форму тоже?
alexey_baranov я считаю, надо проверят данные обычными способами, до того как они попадут в класс, а в классе делать проверку с вызовом исключения только из-за того, что разработчик кода забыл вставить обычную проверку...
Ну да. Форма ведь не знает про устройство сервисного класса Mail. Она знает только, что сейчас от юзера требуется обязательный ввод e-mail адреса. А если меняются требования, то и форма изменяется под эти требования.
Представь себе, почтовый класс в центре картины и сотни классов, которые его используют вокруг него. Где легче осуществлять проверку? Вместо того, чтобы проверять в каждом из сотни данные, а потом использовать этот несчастный класс, легче один раз написать проверку внутри самого класса и выкинуть оттуда если что исключение. так ведь? при этом сразу сразу вот какие вещи - логика проверки у того, кто лучше всех знает, как должна осуществляться проверка. потому что ни один из ста классов не знает точно, что нужно почтовому классу. это может знать только сам почтовый класс - все проверки в одном месте, то есть в сто раза меньше писанины - если надо изменить логику работы почтового класса, придется менять проверку только в одном месте
alexey_baranov Чувствую Леха тебе можно написать книгу "Альтернативное методы и модели программирования" ps: я не смеюсь...
Я не спорю что там проверки не должны осуществляться. Я лишь говорю, что нужно исключить возможную передачу некорректных данных в объект. А сделать это нужно на этапе валидации формы. PHP: <?php // ... $form->addField( FormField::email('email') ->setRequired() ->setMax(50) ); if ($request->isPost()) { $form->import($request->getPost()); if ($form->validate()) { MailService::create() ->setTo($form->getValue('email')) ->setSubject('Hello'); ->send(); } }