0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Исключения - один из немногих примеров удачного использования наследования. В этом уроке мы научимся создавать свои исключения и перехватывать их.</p>
1
<p>Исключения - один из немногих примеров удачного использования наследования. В этом уроке мы научимся создавать свои исключения и перехватывать их.</p>
2
<p>Обычно исключения используются так. Ближе к началу программы стоит конструкция<em>try/catch</em>, которая ловит исключения и показывает пользователю адекватное сообщение:</p>
2
<p>Обычно исключения используются так. Ближе к началу программы стоит конструкция<em>try/catch</em>, которая ловит исключения и показывает пользователю адекватное сообщение:</p>
3
<p>Но как понять что случилось? Иногда это важно. Разные ошибки могут приводить к разному поведению программы. Кроме того, не все ошибки требуют обработки в текущем месте программы.</p>
3
<p>Но как понять что случилось? Иногда это важно. Разные ошибки могут приводить к разному поведению программы. Кроме того, не все ошибки требуют обработки в текущем месте программы.</p>
4
<p>Разделять ошибки можно с помощью разных классов (или интерфейсов) наследующихся от класса<em>Exception</em>, который в свою очередь реализует интерфейс<a>Throwable</a>. По техническим причинам, реализовать этот интерфейс напрямую нельзя, поэтому остаётся только один путь - наследование.</p>
4
<p>Разделять ошибки можно с помощью разных классов (или интерфейсов) наследующихся от класса<em>Exception</em>, который в свою очередь реализует интерфейс<a>Throwable</a>. По техническим причинам, реализовать этот интерфейс напрямую нельзя, поэтому остаётся только один путь - наследование.</p>
5
<p>Причём в отличие от других примеров наследования, в исключениях редко нужно добавлять или изменять поведение. Основная цель использования наследования исключений - описание всех возможных типов ошибок.</p>
5
<p>Причём в отличие от других примеров наследования, в исключениях редко нужно добавлять или изменять поведение. Основная цель использования наследования исключений - описание всех возможных типов ошибок.</p>
6
<p>Теперь посмотрим как этим можно воспользоваться:</p>
6
<p>Теперь посмотрим как этим можно воспользоваться:</p>
7
<p>Конструкция<em>try/catch</em>работает очень похоже на<em>switch</em>, но только для исключений. С её помощью можно описать обработку каждого типа исключений добавив новый блок<em>catch</em>. Во время срабатывания исключения, PHP проверяет каждый блок<em>catch</em>на<em>instanceof</em>, начиная с верхнего. Поэтому порядок блоков<em>catch</em>имеет важное значение.</p>
7
<p>Конструкция<em>try/catch</em>работает очень похоже на<em>switch</em>, но только для исключений. С её помощью можно описать обработку каждого типа исключений добавив новый блок<em>catch</em>. Во время срабатывания исключения, PHP проверяет каждый блок<em>catch</em>на<em>instanceof</em>, начиная с верхнего. Поэтому порядок блоков<em>catch</em>имеет важное значение.</p>
8
<p>В самом PHP уже есть иерархия исключений, которая позволяет разделять реакцию на разные типы ошибок:</p>
8
<p>В самом PHP уже есть иерархия исключений, которая позволяет разделять реакцию на разные типы ошибок:</p>
9
<p>interface Throwable |- Error implements Throwable |- ArithmeticError extends Error |- DivisionByZeroError extends ArithmeticError |- AssertionError extends Error |- ParseError extends Error |- TypeError extends Error |- ArgumentCountError extends TypeError |- Exception implements Throwable |- ClosedGeneratorException extends Exception |- DOMException extends Exception |- ErrorException extends Exception |- IntlException extends Exception |- LogicException extends Exception |- BadFunctionCallException extends LogicException |- BadMethodCallException extends BadFunctionCallException |- DomainException extends LogicException |- InvalidArgumentException extends LogicException |- LengthException extends LogicException |- OutOfRangeException extends LogicException |- PharException extends Exception |- ReflectionException extends Exception |- RuntimeException extends Exception |- OutOfBoundsException extends RuntimeException |- OverflowException extends RuntimeException |- PDOException extends RuntimeException |- RangeException extends RuntimeException |- UnderflowException extends RuntimeException |- UnexpectedValueException extends RuntimeException</p>
9
<p>interface Throwable |- Error implements Throwable |- ArithmeticError extends Error |- DivisionByZeroError extends ArithmeticError |- AssertionError extends Error |- ParseError extends Error |- TypeError extends Error |- ArgumentCountError extends TypeError |- Exception implements Throwable |- ClosedGeneratorException extends Exception |- DOMException extends Exception |- ErrorException extends Exception |- IntlException extends Exception |- LogicException extends Exception |- BadFunctionCallException extends LogicException |- BadMethodCallException extends BadFunctionCallException |- DomainException extends LogicException |- InvalidArgumentException extends LogicException |- LengthException extends LogicException |- OutOfRangeException extends LogicException |- PharException extends Exception |- ReflectionException extends Exception |- RuntimeException extends Exception |- OutOfBoundsException extends RuntimeException |- OverflowException extends RuntimeException |- PDOException extends RuntimeException |- RangeException extends RuntimeException |- UnderflowException extends RuntimeException |- UnexpectedValueException extends RuntimeException</p>
10
<p>Перехват любого базового исключения, автоматически влечёт за собой перехват всех наследников текущего класса. Например, если в блоке<em>catch</em>перехватывать<em>RuntimeException</em>, то этот блок поймает все ошибки, входящие в иерархию<em>RuntimeException</em>.</p>
10
<p>Перехват любого базового исключения, автоматически влечёт за собой перехват всех наследников текущего класса. Например, если в блоке<em>catch</em>перехватывать<em>RuntimeException</em>, то этот блок поймает все ошибки, входящие в иерархию<em>RuntimeException</em>.</p>
11
<p>В PHP есть негласное правило о том, как работать с иерархиями исключений. Любая программа, должна определять своё собственное высокоуровневое исключение, которое наследуется от<em>RuntimeException</em>. Все остальные исключения библиотеки наследуются от него. Такой подход позволяет изолировать обработку ошибок конкретной библиотеки буквально одним блоком<em>catch</em>. Например, в HTTP-клиенте<a>Guzzle</a>, базовое исключение<a>TransferException</a>. Это значит, что среди всех ошибок мы можем перехватить ошибки этого клиента:</p>
11
<p>В PHP есть негласное правило о том, как работать с иерархиями исключений. Любая программа, должна определять своё собственное высокоуровневое исключение, которое наследуется от<em>RuntimeException</em>. Все остальные исключения библиотеки наследуются от него. Такой подход позволяет изолировать обработку ошибок конкретной библиотеки буквально одним блоком<em>catch</em>. Например, в HTTP-клиенте<a>Guzzle</a>, базовое исключение<a>TransferException</a>. Это значит, что среди всех ошибок мы можем перехватить ошибки этого клиента:</p>
12
<h2>Блок finally</h2>
12
<h2>Блок finally</h2>
13
<p>В некоторых ситуациях бывает нужно продолжить работу независимо от того, возникло исключение или нет. Используя только<em>try/catch</em>, эту задачу нельзя выполнить без дублирования. Придётся размещать код как после всей конструкции<em>try/catch</em>, так и в каждом блоке<em>catch</em>.</p>
13
<p>В некоторых ситуациях бывает нужно продолжить работу независимо от того, возникло исключение или нет. Используя только<em>try/catch</em>, эту задачу нельзя выполнить без дублирования. Придётся размещать код как после всей конструкции<em>try/catch</em>, так и в каждом блоке<em>catch</em>.</p>
14
<p>Это привело к тому, что саму конструкцию расширили, добавив в неё блок<em>finally</em>. Этот блок вызывается в самом конце и в любом случае:</p>
14
<p>Это привело к тому, что саму конструкцию расширили, добавив в неё блок<em>finally</em>. Этот блок вызывается в самом конце и в любом случае:</p>
15
15