Обработка ошибок и исключений в PHP

    Эта «небольшая» статейка является развитием темы затронутой в этой статье.
    Как известно, PHP зародился довольно давно и уже тогда возник вопрос, что делать с возникающими ошибками. Perl, который является несомненным прародителем PHP по умолчанию не имел какой-либо системы обработки ошибок. При возникновении любой ошибки сервер выбрасывал 500-ю ошибку и на этом все заканчивалось. Поэтому Warnings, Fatal Errors и Notices были настоящим прорывом в облегчении и без того нелегкого труда программиста. Однако время шло, механизмы PHP не менялись, а технологии, как известно, на месте стоять не любят.

    И вот в PHP 5.0, наконец-то, в арсенале программистов появилось такое мощное средство как исключение или Exception. Достоинств у Exception много, опишу лишь некоторые (возможно, я выражаюсь неточно или даже безграмотно, но мне было просто лень выискивать научные термины для описания преимуществ, потому описаны они «своими словами»):
    • Сквозная генерация. Это означает, что возникновение исключения где либо в коде будет приводит к последовательному выходу из управляющих конструкций и функций до первого блока catch либо до функции main (с выдачей соответствующей ошибки в поток) основного скрипта
    • Возможность переопределения основного класса Exception через наследование
    • Возможность обработки нескольких типов исключений одновременно

    Возможности обработки стандартных ошибок PHP крайне ограничены:
    • Можно заблокировать при помощи @
    • Можно установить свой обработчик при помощи set_error_handler
    • Можно сгенерировать свою ошибку при помощи trigger_error

    Ясно, что стандартный механизм обработки ошибок устарел и присутствует в языке только из соображений совместимости.
    В этой небольшой статье я попробую осветить, как можно сделать обработку ошибок универсальной, переведя ее на использование механизма исключений.
    Основная идея: ставим свой обработчик для стандартных ошибок и «бросаем» исключение в нем:
    1. <?php
    2. class MyException extends Exception {
    3.    public function __construct($message, $errorLevel = 0, $errorFile = '', $errorLine = 0) {
    4.       parent::__construct($message, $errorLevel);
    5.       $this->file = $errorFile;
    6.       $this->line = $errorLine;
    7.    }
    8. }
    9. set_error_handler(create_function('$c, $m, $f, $l', 'throw new MyException($m, $c, $f, $l);'), E_ALL);
    10. ?>
    * This source code was highlighted with Source Code Highlighter.

    Этот код необходимо вынести в отдельный файл и подключать его только один раз. Класс MyException расширяет стандартный класс Exception добавлением двух дополнительных параметров в конструктор: файла и номера строки с ошибкой.
    Функция set_error_handler устанавливает в качестве обработчика ошибок динамически созданную lambda-функцию (callback), которая и генерирует исключение в случае возникновения ошибки. Особенно прошу обратить внимание на второй параметр функции set_error_handler. Этот параметр очень важен, так как он определяет для каких типов ошибок будет вызываться пользовательский (то есть наш) обработчик, а для каких стандартный. В данном примере, я установил значение E_ALL, что означает, что обработчик будет вызываться для всех типов ошибок.
    Если мы не хотим обрабатывать некоторые типы ошибок, например, Notice, то мы можем запросто указать это:
    set_error_handler(create_function('$c, $m, $f, $l', 'throw new MyException($m, $c, $f, $l);'), E_ALL & ~E_NOTICE);* This source code was highlighted with Source Code Highlighter.

    Однако идеальным подходом, как мне кажется будет все таки обработка всех ошибок, но для некоторых типов, в частности, notice, было бы целесообразно не выкидывать exception, а просто выводить информацию на экран:
    set_error_handler(create_function('$c, $m, $f, $l', 'if ($c === E_NOTICE) {echo 'This is notice: '.$m} else {throw new MyException($m, $c, $f, $l);}'), E_ALL);* This source code was highlighted with Source Code Highlighter.

    Теперь рассмотрим приближенный к жизни пример. Задача:
    Есть форма регистрации на сайте, необходимо реализовать при помощи исключений обработку ошибок валидации и выдачу соответствующих предупреждений для пользователя.
    Сложности здесь собственно две:
    1. Выводить все ошибки одновременно, а не по одной
    2. Отделить обработку ошибок валидации от обработки прочих исключений

    Решение:
    Главной сложностью здесь для нас будет то самое пресловутое преимущество Exception, которое заключается в том, что при «бросании» исключения происходит выход из управляющих конструкций до первого блока catch (или до конца скрипта). Для того, чтобы обойти этот подводный камень определим новый класс-потомок FormFieldsListException, в котором реализуем механизм накопления ошибок, а «бросать» исключение будем только после валидации всех полей. В классе FormFieldsListException определяем защищенный (protected) член $_list, в котором будем хранить данные. Для упрощения работы с массивом $_list указываем, что класс будет реализовывать два интерфейса: ArrayAccess для доступа к элементам массива и Iterator для работы в цикле. При инициализации метода проверки валидации создаем объект FormFieldsListException, а затем по мере определения ошибок добавляем их в объект FormFieldsListException, как в обычный массив.
    1. <?php
    2. class FormFieldsListException extends Exception implements ArrayAccess, Iterator {
    3.   protected $_list = array();
    4.   
    5.   public function __construct() {
    6.   }
    7.   
    8.   public function offsetExists($index) {
    9.     return isset($this->_list[$index]);
    10.   }
    11.   
    12.   public function offsetGet($index) {
    13.     return $this->_list[$index];
    14.   }
    15.   
    16.   public function offsetSet($index, $value) {
    17.     if (isset($index)) {
    18.       $this->_list[$index] = $value;
    19.     }
    20.     else {
    21.       $this->_list[] = $value;
    22.     }
    23.   }
    24.   
    25.   public function offsetUnset($index) {
    26.     unset($this->_list[$index]);
    27.   }
    28.   
    29.   public function current() {
    30.     return current($this->_list);
    31.   }
    32.   
    33.   public function key() {
    34.     return key($this->_list);
    35.   }
    36.   
    37.   public function next() {
    38.     return next($this->_list);
    39.   }
    40.   
    41.   public function rewind() {
    42.     return reset($this->_list);
    43.   }
    44.   
    45.   public function valid() {
    46.     return (bool) $this->current();
    47.   }
    48. }
    49. ?>
    * This source code was highlighted with Source Code Highlighter.

    После окончания процедуры валидации проверяем были ли занесены какие-то сообщения об ошибках. Если да то «бросаем» подготовленный объект исключения.
    Для отлова исключения используем два блока catch: для FormFieldsListException и для всех остальных исключений. Это позволяет задать различные виды действий при возникновении различных типов исключений.
    1. <?php
    2. function validateForm() {
    3.    $e = new FormFieldsListException();
    4.    if ($errorInFirstField) {
    5.       $e[] = 'Error in first field';
    6.    }
    7.    if ($errorInSecondField) {
    8.       $e[] = 'Error in second field';
    9.    }
    10.    if ((bool)$e->current()) {
    11.       throw $e;
    12.    }
    13. }
    14.  
    15. try {
    16.    validateForm();
    17. }
    18. catch (FormFieldsListException $error) {
    19.    echo '<b>Errors in the fields</b>:<br />';
    20.    foreach ($error as $e) {
    21.       echo $e.'<br />';
    22.    }
    23. }
    24. catch (Exception $error) {
    25.    echo 'Not validation error! '.$error->getMessage();
    26. }
    27. ?>
    * This source code was highlighted with Source Code Highlighter.

    Вот так вот! :)
    Правильно спроектированная система исключений способна серьезно упростить жизнь программиста, особенно при разработке приложений с использованием шаблона MVC. Как показало это небольшое исследование система обработки исключений в PHP5 таит в себе немалые резервы для модернизации и использования в специфических ситуациях.
    P.S.: Некоторые из программистов, которым я показывал данную статью, считают использование исключений для валидации форм, мягко говоря, не самым лучшим вариантом (кстати, я бы попросил читателей, которые «в теме» высказаться по этому поводу), поэтому прошу считать приведенный пример всего лишь учебным примером, а не руководством к действию.
    P.P.S.: Огромное спасибо товарищу ashofthedream, спор с которым и натолкнул меня на мысль изучить исключения поподробнее.

    UPD: Перенесено в блог PHP
    Share post

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 60

      –1
      а бы добавил error_reporting:
      set_error_handler(create_function('$c, $m, $f, $l', 'if (error_reporting())throw new MyException($m, $c, $f, $l);'), E_ALL);
      для обработчки @ собачки и вообще, display errors
        0
        display_errors не обрабатывает собачку, а лишь скрывает ее присутствие.
        Сверху есть ссылка, на пост с обсуждением проблем, связанных с употреблением собаки (смешно звучит). В моей статье не обсуждается возможность или невозможность применения собаки, а изыскиваются пути избавления от нее с наибольшей выгодой.
        Мне, например, нравится возможность, обрабатывать ошибки, а не решать выводить или не выводить их на экран. Основной плюс в том, что конструктор созданного класса может выполнять любые действия: писать в лог, отсылать на мыло, выводить красивое сообщение об ошибке, да и много чего еще.
          0
          Есть проблема — в случае @ перед include/require error_reporting будет нулевой для всех ошибок, возникающих при выполнении подключаемого файла.
          0
          Неплохо!) Я, как любитель таких вот универсальных штуковин давно хотел придумать себе что-то подобное для обработки ошибок и исключений. Теперь отталкиваться буду от Вашего метода.
            0
            Не мешало бы добавить в статью об пользовательском обработчике исключений - set_exception_handler(functName), котрый вызывает functName, если исключение не перехвачено.
              0
              Да, конечно. Нужно будет добавить, но это уже когда вернусь с работы домой.
              Все-таки нехорошо подрывать капиталистическую экономику так нагло :)
              0
              спасибо за интересный пост.
              это все хорошо, но php 5 еще дааалеко не на всех хостингах к сожалению.
              а вообще рекомендуется писать с включенными
              ini_set("display_errors", "1");
              error_reporting(E_ALL);
              чтобы отсекать все нотисы и ворнинги. фатал ерроры в таких случаях чаще всего будут возникать из за внешних факторов, обусловленных проблемами с базой или хостингом.
                +2
                1. если на хостинге php4 - повод задуматься о смене хостера
                2. Включенное отображение об ошибках на работающем сайте может быть очень полезно при взломе сайта. Так что лучше либо отключать вовсе, либо логировать.
                  +1
                  Лучше отлаживать на одном сервере, а продакшн вести на другом.
                    0
                    мой случай - скрипты на заказ. которые могут приобрести разные люди, и устанавливать их на свои разные хостинги. отдавать скрипты с ошибками в таком случае недопустимо.
                    +2
                    Я уже видел довольно много даже бесплатных хостингов с PHP5.
                    Обратите внимание, что поддержка PHP4 закончилась 31 декабря 2007г. Дальше будут только обновления безопасности.
                      0
                      все верно, было бы хорошо, если бы вторую часть вашего комментария услышали все хостеры мира:)
                        0
                        Вы хотите размещаться одновременно на всех хостерах мира?
                    +7
                    Мне тоже (как и вашим друзьям-разработчикам) кажется, что это не самый удачный пример использования исключений.
                    Обычно, рекомендуют использовать исключения только в нештатных ситуациях, ни в коем случае не применяя их для управления логикой исполнения. И этому есть разумные объяснения. Исключения очень хороши во первых тем, что позволяют снять с кода бросающего исключение ответственность по его обработке, давая возможность среагировать на ошибку коду, который знает как это сделать. Исключения так же хороши тем, что в отличие от подхода с возвратом кода ошибок их невозможно игнорировать (это как раз к тому, почему они хороши для обработки нештатных ситуаций). Плюс вы получаете преимущества связанные с уменьшением дублирования и улучшения читаемости кода обработки ошибок.
                    Если же использовать исключения для организации логики, то в этом они подобны goto, если даже не хуже. Из одного места кода вы вдруг переходите в другое. Повсеместное использование исключений разрушает код. Конечно, грань очень тонкая. Неверные данные, введённые пользователем это штатная или не штатная ситуация? Это зависит от точки зрения разработчика и уровня кода работающего с данными (скажем, на уровне представления неверно введённые данные это нормально, если же вы пытаетесь сохранить объект с этими неверными данными в базу то наверное уже нет.)
                    В вашем случае без исключений вполне можно было бы обойтись. Было бы вполне достаточно вернуть из функции валидации объект с данными об ошибках. Я не вижу, как в этом конкретном примере полезны исключения.
                      0
                      Вот поэтому я и написал, что это пример, который не несет особой смысловой нагрузки.
                      В то же время я указал, что можно использовать разные классы исключений и несколько блоков catch, а если и так не хотите, то можно (даже нужно) определить отдельный класс для исключений приложения в целом и указывать соответствующий тип при обработке в блоке catch.

                      1. class Application_Exception extends Exception {}
                      2. class Validation_Exception extends Exception {}
                      3.  
                      4. try {
                      5.    if ($validationError) {
                      6.       throw new Validation_Exception('Validation error');
                      7.    }
                      8.    if ($applicationError) {
                      9.       throw new Application_Exception('Application error');
                      10.    }
                      11. }
                      12. catch (Validation_Exception $e) {
                      13.    //Обрабатываем только ошибки валидации
                      14. }
                      * This source code was highlighted with Source Code Highlighter.


                      В этом случае, если возникает ошибка валидации, то она обрабатывается "на месте", а ошибка приложения проскакивает дальше.
                        0
                        пример, не несущий смысловой нагрузки, — это не пример, а сферический конь в вакууме. и если опытным это очевидно, то новички пойдут клепать валидаторы через исключения
                          0
                          Ого, тут еще кто-то пишет, через 2 года после публикации.
                          Во-первых, я уже и не помню, почему привел именно такой пример. Наверное, потому что лень было выдумывать что-то реальное для иллюстрации своей мысли.
                          Во-вторых, у каждого разработчика должна быть определенная эволюция. Я и сам через 2 года, написал бы уже по-другому где-то, но новичок должен пройти все этапы большого пути, включая быдлокод, чтобы понимать «что такое хорошо, а что такое плохо».
                            0
                            я как-то перепрыгнул говнокод и совсем от этого не страдаю.
                      +3
                      foreach ($error as $e) {
                      echo $e.'<br />';
                      }

                      ==

                      echo implode('<br />', $error);
                        0
                        Очень ждал материал по исключениям, спасибо. Ибо до сих пор не понимаю их и интерфейсы еще :)
                        0
                        более корректный вариант для обработки значения error_reporting:

                        function my_error_handler($c, $m, $f, $l) {
                        if (error_reporting() & $c)throw new MyException($m, $c, $f, $l);
                        }
                        set_error_handler('my_error_handler');
                          0
                          Тогда еще короче:

                          function my_error_handler($c, $m, $f, $l) {
                            throw new MyException($m, $c, $f, $l);
                          }
                          set_error_handler('my_error_handler', error_reporting());

                          * This source code was highlighted with Source Code Highlighter.
                            +1
                            Это не то же самое. Ваш вариант не учитывает возможные изменения настройки error_reporting во время работы скрипта.
                              0
                              Согласен.
                          0
                          Итерировать по исключению не есть гуд. Не нагружайте инструмент лишним функционалом. FormValidator - отдельно, FormValidationException - отдельно, с кодом ошибки и сообщением (const FIRST_FIELD_ERROR, const LAST_FIELD_ERROR ....).

                          Несколько скомканный пример, а в целом хорошо. Исключения - очень хорошая практика ИМХО.
                            0
                            Данный пример я привел, чтобы показать как, порой необычно, можно применить стандартные инструменты языка (сам когда-то подсмотрел это на одном из форумов, теперь уже не помню где). В конце я указал, что это всего лишь пример.
                            0
                            А я для себя просто реализовал перехват ошибок и запись в лог-файл. Если кому интересно - вот этот класс: http://www.phpclasses.org/browse/package/4552.html
                              0
                              и вы каждый раз в этот лог заглядываете?
                              имхо, в вашем случае нужно сделать крон который будет отсылать лог файл на мейл каждые допустим 10-30 минут
                                0
                                Можно сделать даже проще, в случае ошибок при завершении скрипта отсылать лог на почту.
                                  0
                                  ... и если к вам на страницу с ошибкой придет 1000 человек - вашей почте будет тяжко :)
                                    0
                                    Это точно, но класс скорее для отладки, в продакшн нет смысла его включать. :)
                              0
                              25. echo 'Not validation error! '.$error->getMessage(); — это на каком языке? :) Ладно еще, если в каком-то тестовом примере такой корявый инглиш, но не в публичных же статьях!
                                0
                                И как написать по-английски "не ошибка валидации"?
                                  0
                                  validation passed
                                    +1
                                    Вообще-то тут имеется в виду, что это не ошибка валидации, а какая-то другая.
                                    0
                                    "Не ошибка валидации" писать нельзя даже по-русски: это бред. Это значит "не ошибка", т.е. нет ошибки. Как минимум тогда уж "ошибка не валидации", но это тоже бред. В вашем примере стоило просто написать "другая ошибка" и все было бы понятно.
                                      +1
                                      "валидации не ошибка" (с) Мастер Йода
                                  0
                                  Как-то раз я решил стать "настоящим программистом" (с) и переписать код своей маленькой, но очень милой сердцу cms-ки на эксепшны. Немного погуглив, почитал мысли людей, принципы и подходы которых мне очень близки (не только по исключениям, а вообще - "be simple, we don't need rocket science in code") - Раймонда Чена и Джоэля Спольски:

                                  Exceptions by Joel Spolsky
                                  http://www.joelonsoftware.com/items/2003…

                                  Cleaner, more elegant, and harder to recognize by Raymond Chen
                                  http://blogs.msdn.com/oldnewthing/archiv…

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

                                  Хотя у exception-powered подхода есть свои преимущества, безусловно. Просто для меня они пока не перевесили главный недостаток - некоторого ухудшения читабельности и "прямолинейности" кода.
                                    0
                                    а вот противоположное мнение, от Ивана Сагалаева, которого тоже очень уважаю:
                                    http://softwaremaniacs.org/blog/2005/05/…
                                      0
                                      Странно, а я нашел там не прямо противоположное, а абсолютно такое же мнение...
                                      Хороший пример — это реакция на нехватку памяти. У самого Джоэла притчей во языцех стало то, что нерадивые программисты забывают проверять значение, возвращенное из malloc(). Ну хорошо, проверили мы, что malloc вернул "памяти нет". Что делать? Только отказываться от дальнейшей работы этой функции, что тут другое придумать? Вот исключения и делают это автоматически и надежно, не полагаясь на то, что каждая из цепочки в 50 вызывающих функций не забудет передать наверх каждую ошибку, возникшую в самой глубине менеджера памяти.
                                      0
                                      Ксате интересный пример использования исключений, правда я все таки считаю что не для такого они предназначены (все таки неправильно введеные данные пользователем - это нормальная ситуация), и в реальной жизни применять их в этой ситуации не стоит... Но я бы еще добавил Countable, и строчку if((bool)$e->current()) { заменил бы на if(count($e)) {
                                        +1
                                        В целом эксепшны юзать хорошо. Но переиспользовать их вредно.

                                        Два момента в которых вы имхо ошибаетесь:

                                        - Нет смысла заворачивать fatal errors в исключения. Вы хотите отлавливать их в try .. catch и красиво завершать? Красиво завершать и так получится если юзать set_error_handler. Или же греет мысль что скажем "division by zero" вы сможете отлавливать и продолжать далее как будто так и надо? И это вместо того чтобы вставить (когда заметите) проверку делителя до деления? Мрак.

                                        - Нотисы и варнинги заворачивать и подавно глупо, ведь сакральный смысл их в том, что программа в продакшн режиме сможет продолжать работу, паралельно залогав эту ошибку в error_logе (и/или отослав мыло), а девелопер поправит как только сможет, нестрашно.

                                        Один момент в котором вы имхо придете к неэффективному/сложному коду:
                                        - Использование исключений для штатных ситуаций (емэйл невалиден) лишь плодит try .. catch блоки, а следить за ними (если их много) ненамного легче чем за глобальными переменными (если их много).
                                          0
                                          Нет смысла заворачивать fatal errors в исключения. Вы хотите отлавливать их в try .. catch и красиво завершать? Красиво завершать и так получится если юзать set_error_handler.

                                          set_error_handler установить можно только один раз, а если я хочу в разных модулях обрабатывать ошибки по разному? try...catch блоки как раз дают такую возможность.
                                          Про нотисы я указал, что их можно обработать еще в теле set_error_handler, не генерируя исключение.
                                          Использование исключений для штатных ситуаций (емэйл невалиден) лишь плодит try .. catch блоки, а следить за ними (если их много) ненамного легче чем за глобальными переменными (если их много)

                                          А я ведь не генерировал много try...catch блоков... Я накапливал сообщения об ошибках в теле объекта исключения, а бросал его только один раз, соответственно и обрабатывать его нужно только один раз.
                                          Смысл в том, что для разных типов исключений я бы рекомендовал заводить разные классы, тогда некоторые блоки try...catch будут пропускать исключения наверх - вот и получим необходимую гибкость.
                                            0
                                            try {
                                            validateForm(...)
                                            } catch ($e) {
                                            ...
                                            }
                                            не более удобно чем:
                                            if (!validateForm(..., &$errors) {
                                            ...
                                            }
                                            А помимо неудобства это, хотя выглядит оопэшно, но нарушает инкапсуляцию: код который использует третью библиотеку будет должен знать имена эксепшнов этой библиотеки. Это конечно если есть эксепшны которые не ловятся внутри библиотеки. Иначе нчего особенного, кроме try ... catch которые не по назначению.

                                            Exception - исключительная ситуация, а не рядовая бизнес логика (как валидация емэйла). Сложно представить когда нужно чтобы преимущества эксепшнов (например эскалация эксепшна вверх) были нужны при обнаружении невалидного емэйла. Если ничего кроме возвращения массива ошибок не нужно, то и не нужен всего-то return.
                                              0
                                              Подумайте о том, как реализован validateForm внутри: validateEmail, validateUsername, validateCaptcha, etc. С помощью исключения это может быть реализовано проще и понятнее.
                                                0
                                                А помимо неудобства это, хотя выглядит оопэшно, но нарушает инкапсуляцию: код который использует третью библиотеку будет должен знать имена эксепшнов этой библиотеки.

                                                Если вы используете какую-то библиотеку, то вы, во-первых, должны прочитать API и вам желательно знать имена классов, в нее входящих.
                                                Во-вторых, все классы исключений наследуются от Exception, поэтому если вы не хотите учить имена классов можете просто писать catch(Exception $e).
                                                Как это нарушает инкапсуляцию я вообще не понял... Вы же не выносите код класса за его пределы. Все внутриклассовые ошибки обрабатываются в классе, а ошибки связанные с неправильными параметрами, переданными извне должны генерировать исключение. Лично я тут проблемы не вижу.
                                              0
                                              Насчет первого момента, Fatal Error-ы в пыхе не перехватываются. Нет, конечно перехватить их можно, но... это делается через такую жопу, что это никому и ненужно.

                                              Насчет варнингов в пхп все очень тонко. К примеру по варнингу от mysql_connect, можно выкидывать эксепшн - потому, как варнинг нам сообщит о том, что мы не смогли приконнектица к бд, в том же foreach-е если он будет выкидываца - тоже будет хорошо, потому как сразу заставит посмотреть почему же у нас иногда не те данные имеюца (и такое поведение имхо хорошо и для варнингов с киданием заголовков и кук)... но вот в случае с DOMDocument::loadHTML - такое поведение будет неочень хорошо, потому как он же html нормально распарсит, но кинет варинг, а использовать @ или пустой catch - не очень красиво.
                                                0
                                                > К примеру по варнингу от mysql_connect, можно выкидывать эксепшн.
                                                Кидать эксепшн здесь нужно, зачем только для этого перехватывать варнинги
                                                  0
                                                  потому что я тогда не буду писать сам три строчки в виде
                                                  if(!$connection) {
                                                    throw new ModelConnectionException('я нисмог приконектицо к базеданых')
                                                  }

                                                  А эксепнш будет кинут по варнингу.
                                                    0
                                                    Сомнительное удовольствие
                                                  0
                                                  Да, насчет Fatal Error, это я протупил, признаю. Почему-то показалось, что такие ошибки, как Division By Zero должны быть Fatal Error...
                                                    0
                                                    Не, это ворнинг. Что наводит на мысль, что ворнинг в пхп это нечто большее чем просто ворнинг...
                                                0
                                                А можно как то вывести дерево функции в порядке их вызова? То есть ошибка была в функции A() которая была вызвана из функции B() которая была вызвана из функции C(). В standalone языках обычно это дебагер сразу показывает + показывает что было передано в параметрах функции. Есть что то такое в php?
                                                  0
                                                  debug_print_backtrace()
                                                  Работает в любой функции, а не только при ошибке.

                                                  В самом классе Exception есть член trace (содержит всю информацию по стеку функций в виде массива), а таже методы getTrace() и getTraceAsString().

                                                  PS: Для PHP тоже есть отладчики.
                                                    0
                                                    Спасибо! :)
                                                  0
                                                  Довольно просто и функционально, такой ООПшный способ навешивания обработчика мне понравился. Но соглашусь с писавшими выше, что валидатор форм лучше делать отдельно.
                                                    0
                                                    Простите за «небольшой» некропостинг, но поскольку статья на втором месте в яндексе, то хотелось бы указать небольшой АПДЕЙТ:
                                                    Уже довольно давно существует класс ErrorException, так что идея с MyException давно реализована в ядре пхп, и свой велосипед не нужен. Ну и с валидатором тоже конечно кошмарно, но вы это сами указали.
                                                    ПС: я понимаю что 8 лет прошло, просто статья по прежнему в топе)
                                                      0
                                                      Лол, не знал, что статья в топе. Может, стоит закрыть?
                                                        0
                                                        Я бы написал апдейт и жирненько в начале о том, что статья устарела и осталась для истории. Мне например было интересно прочитать такую древность. Кто-то может узнает про ErrorException, ведь наверняка много таких велосипедов до сих пор гуляет в сети…

                                                    Only users with full accounts can post comments. Log in, please.