Php исключения обработка всех ошибок

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

Этот код необходимо вынести в отдельный файл и подключать его только один раз. Класс 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, а просто выводить информацию на экран:

  1. Выводить все ошибки одновременно, а не по одной
  2. Отделить обработку ошибок валидации от обработки прочих исключений
  1. class FormFieldsListException extends Exception implements ArrayAccess, Iterator
  2. protected $_list = array();
  3. public function __construct()
  4. >
  5. public function offsetExists($index)
  6. return isset($ this ->_list[$index]);
  7. >
  8. public function offsetGet($index)
  9. return $ this ->_list[$index];
  10. >
  11. public function offsetSet($index, $value)
  12. if (isset($index))
  13. $ this ->_list[$index] = $value;
  14. >
  15. else
  16. $ this ->_list[] = $value;
  17. >
  18. >
  19. public function offsetUnset($index)
  20. unset($ this ->_list[$index]);
  21. >
  22. public function current()
  23. return current($ this ->_list);
  24. >
  25. public function key()
  26. return key($ this ->_list);
  27. >
  28. public function next()
  29. return next($ this ->_list);
  30. >
  31. public function rewind()
  32. return reset($ this ->_list);
  33. >
  34. public function valid()
  35. return ( bool ) $ this ->current();
  36. >
  37. >
  38. ?>

После окончания процедуры валидации проверяем были ли занесены какие-то сообщения об ошибках. Если да то «бросаем» подготовленный объект исключения.
Для отлова исключения используем два блока catch: для FormFieldsListException и для всех остальных исключений. Это позволяет задать различные виды действий при возникновении различных типов исключений.

  1. function validateForm()
  2. $e = new FormFieldsListException();
  3. if ($errorInFirstField)
  4. $e[] = ‘Error in first field’ ;
  5. >
  6. if ($errorInSecondField)
  7. $e[] = ‘Error in second field’ ;
  8. >
  9. if (( bool )$e->current())
  10. throw $e;
  11. >
  12. >
  13. try
  14. validateForm();
  15. >
  16. catch (FormFieldsListException $error)
  17. echo ‘Errors in the fields:
    ‘ ;
  18. foreach ($error as $e)
  19. echo $e. ‘
    ‘ ;
  20. >
  21. >
  22. catch (Exception $error)
  23. echo ‘Not validation error! ‘ .$error->getMessage();
  24. >
  25. ?>

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

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

Источник

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

В процессе работы программы могут возникать различные ошибки, которые могут прервать работу программы. Например, рассмотрим следующую ситуацию:

$a = 5; $b = 0; $result = $a / $b; echo $result; echo "Конец работы программы";

Программа выводит результат деления. Поскольку делитель равен 0, а на ноль делить нельзя, то при выполнении деления программа завершится, и в браузере мы увидим что-то типа следующего:

Fatal error: Uncaught DivisionByZeroError: Division by zero in D:\localhost\hello.php:11 Stack trace: #0 thrown in D:\localhost\hello.php on line 11

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

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

Для обработки исключений в PHP применяется конструкция try-catch :

try < // код, который может вызвать исключение >catch(Тип_исключения $ex) < // обработка исключения >

Эта конструкция в общем варианте состоит из двух блоков — try и catch . В блок try помещается код, который потенциально может вызвать исключение. А в блоке catch помещается обработка возникшего исключения. Причем каждого типа исключения мы можем определить свою логику обработки. Конкретный тип исключения, который мы хотим обработать, указывается в круглых скобках после оператора catch :

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

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

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

Например, обработаем ошибку с делением на ноль:

try < // код, который может вызвать исключение $a = 5; $b = 0; $result = $a / $b; echo $result; >catch(DivisionByZeroError $ex) < // обработка исключения echo "Произошло исключение:
"; echo $ex . "
"; > echo "Конец работы программы";

В данном случае код деления на ноль, поскольку он может потенциально вызвать ошибку, помещен в блок try .

В блоке catch обрабатывается ошибка типа DivisionByZeroError , которая генерируется при делении на ноль. Вся обработка сводится к выводу информации на экран.

В итоге при выполнении программа выведет следующее:

Произошло исключение: DivisionByZeroError: Division by zero in D:\localhost\hello.php:14 Stack trace: #0 Конец работы программы

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

Типы ошибок и исключений

В PHP для разных ситуаций есть множество типов, которые описывают ошибки. Все эти встроенные типы применяют интерфейс Throwable :

Ошибки и исключения Error, Exception и Throwable в PHP

Все типы делятся на две группы: собственно ошибки (класс Error ) и собственно исключения (класс Exception ). А от классов Error и Exception наследуются классы ошибок и исключений, которые описывают конкретные ситуации. Например, от класса Error наследуется класс ArithmeticError , который описывает ошибки, возникающие при выполнении арифметических операций. А от класса ArithmeticError наследуется класс DivisionByZeroError , который представляют ошибку при делении на ноль.

Блок catch

Конструкция try..catch позволяет определить несколько блоков catch — для обработки различных типов ошибок и исключений:

try < $result = 5 / 0; echo $result; >catch(ParseError $p) < echo "Произошла ошибка парсинга"; >catch(DivisionByZeroError $d)

При возникновении ошибки будет для ее обработки будет выбираться тот блок catch , который соответствует вошникшей ошибки. Так, в данном случае при делении на ноль будет выполняться второй блок catch .

Если бы в блоке try возникла бы ошибка, которая бы не соответствовала типам из блоков catch (в данном случае — типам DivisionByZeroError и ParseError), то такая ошибка не была бы обработана, и соответственно программа бы аварийно завершила свое выполнение.

Блоки catch с более конкретными типами ошибок и исключений должны идти в начале, а более с более общими типа — в конце:

try < $result = 5 / 0; echo $result; >catch(DivisionByZeroError $ex) < echo "На ноль делить нельзя"; >catch(ArithmeticError $ex) < echo "Ошибка при выполнении арифметической операции"; >catch(Error $ex) < echo "Произошла ошибка"; >catch(Throwable $ex)

Класс DivisionByZeroError унаследован от ArithmeticError, который, в свою очередь, унаследован от Error, реализующего интерфейс Throwable. Поэтому класс DivisionByZeroError представляет более конкретный тип и представляемые им ошибки должны обрабатываться в первую очередь. А тип Throwable представляет наиболее общий тип, так как ему соответствуют все возможные ошибки и исключения, поэтому блоки catch с таким типом должны идти в конце.

В данном случае опять же в блоке try происходит ошибка деления на ноль. Но этой ошибке соответствуют все четыре блока catch . Для обработки PHP будет выбирать первый попавшийся, который соответствует типу ошибки. В данном случае это блок для обработки ошибки типа DivisionByZeroError.

Если нам надо обрабатывать в принципе все ошибки и исключения, то мы можем определить только обработку общего для всех них типа Throwable:

Начиная с версии PHP 8.0 в блоке catch можно просто указать тип обрабатываемого исключения, не определяя переменную:

Получение информации об ошибках и исключениях

Интерфейс Throwable предоставляет ряд методов, которые позволяют получить некоторую информацию о возникшем исключении:

  • getMessage() : возвращает сообщение об ошибке
  • getCode() : возвращает код исключения
  • getFile() : возвращает название файла, в котором возникла ошибка
  • getLine() : возвращает номер строки, в которой возникла ошибка
  • getTrace() : возвращает трассировку стека
  • getTraceAsString() : возвращает трассировку стека в виде строки

Применим некоторые из этих методов:

try < $result = 5 / 0; echo $result; >catch(DivisionByZeroError $ex) < echo "Сообщение об ошибке: " . $ex->getMessage() . "
"; echo "Файл: " . $ex->getFile() . "
"; echo "Номер строки: " . $ex->getLine() . "
"; >
Сообщение об ошибке: Division by zero Файл: D:\localhost\hello.php Номер строки: 11

Блок finally

Конструкция try..catch также может определять блок finally . Этот блок выполняется в конце — после блока try и catch вне зависимости, возникла или нет ошибка. Нередко блок finally используется для закрытия ресурсов, которые применяются в блоке try.

try < $result = 5 / 0; echo $result . "
"; > catch(Throwable $ex) < echo "Ошибка при выполнении программы
"; > finally < echo "Блок finally
"; > echo "Конец работы программы";
Ошибка при выполнении программы Блок finally Конец работы программы

Конструкция try..catch..finally может содержать либо все три блока, либо только два блока try и либо блок catch , либо блок finally .

Источник

Исключения PHP: Try Catch для обработки ошибок

Sajal Soni

Sajal Soni Last updated Dec 20, 2021

В этом посте вы узнаете, как использовать обработку исключений в PHP. Начиная с PHP 5, мы можем использовать блоки try catch для обработки ошибок — это лучший способ обработки исключений и управления потоком вашего приложения. В этой статье мы рассмотрим основы обработки исключений вместе с несколькими примерами из реального мира.

Что такое исключение?

В PHP 5 появилась новая модель ошибок, которая позволяет вам кидать и ловить исключения в вашем приложении — это лучший способ обработки ошибок, чем то, что мы имели в более старых версиях PHP. Все исключения являются экземплярами базового класса Exception , который мы можем расширить, чтобы ввести наши собственные пользовательские исключения.

Здесь важно отметить, что обработка исключений отличается от обработки ошибок. При обработке ошибок мы можем использовать функцию set_error_handler для установки нашей настраиваемой функции обработки ошибок, чтобы всякий раз, когда срабатывает ошибка, она вызывала нашу функцию обработки ошибок. Таким образом, вы можете управлять ошибками. Однако, как правило, некоторые виды ошибок не восстанавливаются и прекращают выполнение программы.

С другой стороны, исключения — это что-то, что умышленно вызывает код, и ожидается, что он будет пойман в какой-то момент вашего приложения. Таким образом, мы можем сказать, что исключения восстанавливаются, а не определенные ошибки, которые не подлежат восстановлению. Если исключение, которое выбрасывается, попадает где-то в ваше приложение, выполнение программы продолжается с момента, когда исключение было поймано. А исключение, которое не попадает нигде в ваше приложение, приводит к ошибке, которое останавливает выполнение программы.

Поток управления обработкой исключений

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

Exception handling in a try catch finally block

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

// code before the try-catch block 

Источник

Читайте также:  Src package in java
Оцените статью