Меню Закрыть

Throw new exception php

Содержание

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

Давайте сразу взглянем на пример сгенерированного исключения ( и впоследствии перехваченного ):

В приведенном выше примере я продемонстрировал использование TRY и CATCH , в котором исключение всегда сгенерировано ( только ради примера ):

  1. Внутри блока TRY мы проверяем, равняется ли цифра 1 цифре 2 . Так как она не равняется ( и никогда не будет равняться ), мы генерируем исключение с сообщением “ 1 не равняется 2! ”;
  2. Внутри блока CATCH мы перехватываем исключение и выводим соответствующее сообщение.
  • TRY : внутри блока PHP try мы задаем логику приложения. Этот блок содержит код, который может или не может сгенерировать исключение;
  • CATCH : блок CATCH будет перехватывать любые исключения, проявившиеся в предыдущем блоке TRY . Код внутри блока CATCH будет исполнен только в случае обнаружения исключения;
  • FINALLY : если вы используете PHP 5.5 и выше, то вы можете использовать блок FINALLY . Расположенный в нем код исполняется всегда, вне зависимости от того, было ли обнаружено исключение.

Когда используются исключения?

Исключения используются, когда результат операции отличается от того, что ожидало ваше приложение. К примеру, если ваше приложение пытается прочитать CSV-файл на сервере, а этого файла не существует, то можно сгенерировать исключение. Использование PHP try catch в примере:

В приведенном выше примере использования в PHP try exception мы генерируем исключение тогда, когда не можем открыть запрашиваемый файл. И генерируем мы его, так как файл должен был существовать. Примеры ситуаций, когда вы можете генерировать исключения:

  1. Ваше PHP-приложение не может подключиться к MySQL ;
  2. Ошибка при запросе к базе данных;
  3. Ошибка при запросе к API ;
  4. Получен некорректный тип запроса;
  5. Отсутствуют необходимые переменные $_POST или $_GET .

Нужно ли перехватывать все исключения?

Лично я так не считаю. К примеру: вам не удается подключиться к базе данных, и генерируется исключение, нужно ли тогда исполнять весь оставшийся код? Если весь последующий код привязан к базе данных, которой просто не существует, то зачем же его исполнять?

По моему мнению, исключения нужно перехватывать с помощью PHP try catch finally только, если это не оказывает негативного влияния на остальные функции приложения.

Например: если API-запрос к внешнему сервису выдает ошибку, то вы можете перехватить исключение и вывести дружественное пользователю сообщение « Невозможно подключиться к базе данных » или « Информация о погоде недоступна ».

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

Данная публикация представляет собой перевод статьи « Php Exceptions: Try & Catch » , подготовленной дружной командой проекта Интернет-технологии.ру

Содержание

Модель исключений (exceptions) в PHP 5 схожа с используемыми в других языках программирования. Исключение можно сгенерировать (как говорят, "выбросить") при помощи оператора throw, и можно перехватить (или, как говорят, "поймать") оператором catch. Код генерирующий исключение, должен быть окружен блоком try, для того чтобы можно было перехватить исключение. Каждый блок try должен иметь как минимум один соответствующий ему блок catch или finally.

Генерируемый объект должен принадлежать классу Exception или наследоваться от Exception. Попытка сгенерировать исключение другого класса приведет к неисправимой ошибке.

catch

Можно использовать несколько блоков catch, перехватывающих различные классы исключений. Нормальное выполнение (когда не генерируются исключения в блоках try или когда класс сгенерированного исключения не совпадает с классами, объявленными в соответствующих блоках catch) будет продолжено за последним блоком catch. Исключения так же могут быть сгенерированы (или вызваны еще раз) оператором throw внутри блока catch.

При генерации исключения код следующий после описываемого выражения исполнен не будет, а PHP предпримет попытку найти первый блок catch, перехватывающий исключение данного класса. Если исключение не будет перехвачено, PHP выдаст сообщение об ошибке: "Uncaught Exception . " (Неперехваченное исключение), если не был определен обработчик ошибок при помощи функции set_exception_handler() .

Читайте также:  Mx записи домена что это

finally

В PHP 5.5 и более поздних версиях также можно использовать блок finally после или вместо блока catch. Код в блоке finally всегда будет выполняться после кода в блоках try и catch, вне зависимости было ли брошено исключение или нет, перед тем как продолжится нормальное выполнение кода. whether an exception has been thrown, and before normal execution resumes.

Примечания

Внутренние функции PHP в основном используют сообщения об ошибках, и только новые объектно-ориентированные расширения используют исключения. Однако, ошибки можно легко преобразовать в исключения с помощью класса ErrorException.

Примеры

Пример #3 Выброс исключений

function inverse ( $x ) <
if (! $x ) <
throw new Exception ( ‘Деление на ноль.’ );
>
return 1 / $x ;
>

try <
echo inverse ( 5 ) . "
" ;
echo inverse ( 0 ) . "
" ;
> catch ( Exception $e ) <
echo ‘Выброшено исключение: ‘ , $e -> getMessage (), "
" ;
>

// Продолжение выполнения
echo "Hello World
" ;
?>

Результат выполнения данного примера:

Пример #4 Вложенные исключения

function inverse ( $x ) <
if (! $x ) <
throw new Exception ( ‘Деление на ноль.’ );
>
return 1 / $x ;
>

try <
echo inverse ( 5 ) . "
" ;
> catch ( Exception $e ) <
echo ‘Поймано исключение: ‘ , $e -> getMessage (), "
" ;
> finally <
echo "Первое finally.
" ;
>

try <
echo inverse ( 0 ) . "
" ;
> catch ( Exception $e ) <
echo ‘Поймано исключение: ‘ , $e -> getMessage (), "
" ;
> finally <
echo "Второе finally.
" ;
>

// Продолжение нормального выполнения
echo "Hello World
" ;
?>

Результат выполнения данного примера:

Пример #5 Вложенные исключения

class Test <
public function testing () <
try <
try <
throw new MyException ( ‘foo!’ );
> catch ( MyException $e ) <
// повторный выброс исключения
throw $e ;
>
> catch ( Exception $e ) <
var_dump ( $e -> getMessage ());
>
>
>

$foo = new Test ;
$foo -> testing ();

Содержание:

Если ты изучаешь ООП, то наверняка натыкался на понятие исключения, а может даже уже видел его где-то в коде. В этом уроке я постараюсь объяснить, что такое исключение в PHP7 и зачем они нужны. Расскажу когда, какое и как правильно применять то или иное исключение при разработке.

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

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

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

Согласитесь, удобно. Вместо того, чтобы просто возвращать false в случае, когда срабатывает условие if (count($category->products) > 0) , лучше кинуть исключение и как-то оповестить пользователя о каких-либо возникших исключительных ситуациях. Если же мы просто вернём false , то мы сами со временем не сможем понять, что именно там случилось и почему этот метод не работает. Поэтому, я советую всегда пользоваться исключениями, но слишком не увлекаясь этим делом.

Класс Exception

Исключение (Exception) – это объект, являющийся экземпляром встроенного класса Exception . Этот объект создаётся для хранения информации о произошедшей ошибке и для вывода сообщений о ней.

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

  • getMessage() – возвращает строку, которая была передана конструктору и содержит сообщение об ошибке.
  • getCode() – возвращает код ошибки (тип int), который был передан конструктору.
  • getFile() – возвращает имя файла в котором было сгенерировано исключение.
  • getLine() – возвращает номер строки в которой было сгенерировано исключение.
  • getTrace() – возвращает многомерный массив, содержащий последовательность методов, вызов которых привёл к генерированию исключения. Так же содержит параметры, которые были переданы этим методам и номера строк, где осуществлялись вызовы.
  • getTraceAsString() – возвращает строковую версию данных, которые возвращает метод getTrace() .
  • __toString() – магический метод, который вызывается, когда экземпляр класса Exception приводится к строке.
Читайте также:  Call of duty stalingrad

Генерация исключений

Для генерации исключения используется ключевое слово throw и экземпляр класса Exception . С английского throw переводится как «бросать», что очень точно описывает поведение этого оператора. Он генерирует (бросает) исключение в каком-либо методе (в котором может случиться нестандартная, исключительная ситуация) и останавливает дальнейшее выполнение кода, тем самым предоставляя возможность обработать это исключение в методе (в любом месте приложения), который будет вызывать данный метод с брошенным исключением.

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

И так, метод, который вызывает метод, в котором в свою очередь может быть брошено исключение, должен сам его обрабатывать. Обработка исключения производится при помощи операторов try — catch . Блок кода, который может поймать исключение, располагается после try . Блок кода, который обрабатывает исключение, располагается после оператора catch . В переводе с английского try означает «пытаться», что очень точно отражает суть этого оператора, ведь мы пытаемся выполнить блок кода после него, а если не получается то выполняется блок кода после catch . Catch переводится как «ловить». Он фактически «ловит» сгенерированное исключение. В примере ниже мы ловим исключение из метода setName() класса User из примера выше:

Ловим исключение в блоке try :

Но так делать не рекомендуется ( try/catch и throw на одном уровне). В этом случае проще написать if !

Оператор catch внешне напоминает объявление метода с уточнением типа его аргумента. Когда генерируется исключение, управление передаётся оператору catch , при этом в качестве аргумента ему передаётся объект типа Exception .

Создание подклассов класса Exception

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

Пример собственного класса исключения:

Полная иерархия исключений в PHP7

Throwable

Throwable — это даже не исключение, а интерфейс, который реализуют все остальные рассматриваемые классы. Добавлен в PHP7.

Exception

Базовый класс для исключений. Стандартная библиотека SPL вводит две группы исключений, два надкласса: для исключений в логике: LogicException и исключений времени исполнении RuntimeException .

LogicException

Используется, когда ваш код возвращает значение, которое не должен возвращать. Часто вызывается при разных багах в коде. Потомки этого класса используются в более специализированных ситуациях. Если ни одна из них не подходит под ваш случай, можно использовать LogicException.

BadFunctionCallException

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

BadMethodCallException

Подкласс BadFunctionCallException . Аналогично ему используется для методов, которые не существуют или которым передано неверное число параметров. Всегда используйте внутри __call() , в основном для этого оно и применяется.

Пример использования этих двух исключений:

DomainException

Если в коде подразумеваются некие ограничения для значений, то это исключение можно вызывать, когда значение выходит за эти ограничения. Например, у вас дни недели обозначаются числами от 1 до 7, а ваш метод получает внезапно на вход 0 или 9, или, скажем, вы ожидаете число, обозначающее количество зрителей в зале, а получаете отрицательное значени. В таких случаях и вызывается DomainException. Также можно использовать для разных проверок параметров, когда параметры нужных типов, но при этом не проходят проверку на значение. Например:

InvalidArgumentException

Вызываем, когда ожидаемые аргументы в функции/методе некорректно сформированы. Например, ожидается целое число, а на входе строка или ожидается GET, а пришел POST и т.п.

LengthException

Вызываем, если длина чего-то слишком велика или мала. Например, имя файла слишком короткое или длина строки слишком большая.

Читайте также:  Портативная колонка для айфона

RuntimeException

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

OutOfBoundsException

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

Пример использования в реализации ArrayAccess :

OutOfRangeException

Используется, когда встречаем некорректный индекс, но на этот раз ошибка должна быть обнаружена ещё до прогона кода, например, если мы пытаемся адресовать элемент массива, который в принципе не поддерживается. То есть если функция, возвращающая день недели по его индексу от 1 до 7, получает внезапно 9, то это DomainException — ошибка логики, а если у нас есть массив с днями недели с индексами от 1 до 7, а мы пытаемся обратиться к элементу с индексом 9, то это уже OutOfRangeException .

OverflowException

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

UnderflowException

Обратная OverflowException ситуация, когда, например, класс-контейнер имеет недостаточно элементов для осуществления операции. Например, когда он пуст, а вы пытаетесь удалить элемент.

RangeException

Вызывается, когда значение выходит за границы некоего диапазона. Похоже на DomainException , но используется при возврате из функции, а не при входе. Если мы не можем вернуть легитимное значение, мы выбрасываем это исключение. То есть, к примеру, функция у вас принимает целочисленный индекс и использует другую функцию, чтоб получить некое значение по этой сущности. Та функция вернула null, но ваша функция не имеет права возвращать Null. В таком случае можно применить это исключение. То есть между ними примерно такая же разница, как между OutOfBoundsException и OutOfRangeException .

UnexpectedValueException

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

Важно, что, в отличие от InvalidArgumentException , здесь мы имеем дело, в основном, с возвращаемыми значениями. Часто мы заранее не можем быть уверены в том, что придет в ответе от функции (особенно сторонней). Скажем, мы используем некую стороннюю функцию, использующую API ВКонтакте, и возвращющую количество постов для пользователя. Она всегда возвращала целое неотрицательное число, и вдруг неожиданно возвращает отрицательное число. Это не соответствует документации. Соответственно, чтобы подстраховаться от таких ситуаций, мы можем проверять результат такого вызова и, если он отличается от ожидаемого, выбрасывать UnexpectedValueException.

Вот пример, когда у нас есть список констант, и функция getValueOfX должна гарантированно возвращать значение одной из них.

Error

Добавлено в PHP7 для обработки фатальных ошибок. То есть многие из ошибок, которые раньше приводили к Fatal Error , в PHP7 могут обрабатываться в блоках try/catch . Эти ошибки вызываются самим PHP, нет нужды их вызывать, как Exception. Класс Error имеет три подкласса:

AssertionError

Вызывается, когда условие, заданное методом assert() , не выполняется.

ParseError

Для ошибок парсинга, когда подключаемый по include/require код вызывает ошибку синтаксиса, ошибок функции eval() и т.п.

TypeError

Используется для ошибок несоответствия типов данных. В PHP7 введена опциональная строгая типизация. Вот для поддержки ошибок, связанных с ней, и служит этот класс. Например, если функция ожидает на входе аргумент типа int , а вы ее вызываете со строковым аргументом.

Учебный пример, в котором есть примеры использования всех классов исключений:

Вот и всё. Думаю, материал буде полезен как новичкам, так и более продвинутым программистам. Я постарался систематизировать информацию об исключениях в одной статье.

Документация по исключениям в PHP7 здесь .

Рекомендуем к прочтению

Добавить комментарий

Ваш адрес email не будет опубликован.