Russian (Pусский) translation by Anna Goorikova (you can also view the original English article)
В этом посте вы узнаете, как использовать обработку исключений в PHP. Начиная с PHP 5, мы можем использовать блоки try catch для обработки ошибок - это лучший способ обработки исключений и управления потоком вашего приложения. В этой статье мы рассмотрим основы обработки исключений вместе с несколькими примерами из реального мира.
Что такое исключение?
В PHP 5 появилась новая модель ошибок, которая позволяет вам кидать и ловить исключения в вашем приложении - это лучший способ обработки ошибок, чем то, что мы имели в более старых версиях PHP. Все исключения являются экземплярами базового класса Exception
, который мы можем расширить, чтобы ввести наши собственные пользовательские исключения.
Здесь важно отметить, что обработка исключений отличается от обработки ошибок. При обработке ошибок мы можем использовать функцию set_error_handler
для установки нашей настраиваемой функции обработки ошибок, чтобы всякий раз, когда срабатывает ошибка, она вызывала нашу функцию обработки ошибок. Таким образом, вы можете управлять ошибками. Однако, как правило, некоторые виды ошибок не восстанавливаются и прекращают выполнение программы.
С другой стороны, исключения - это что-то, что умышленно вызывает код, и ожидается, что он будет пойман в какой-то момент вашего приложения. Таким образом, мы можем сказать, что исключения восстанавливаются, а не определенные ошибки, которые не подлежат восстановлению. Если исключение, которое выбрасывается, попадает где-то в ваше приложение, выполнение программы продолжается с момента, когда исключение было поймано. А исключение, которое не попадает нигде в ваше приложение, приводит к ошибке, которое останавливает выполнение программы.
Поток управления обработкой исключений
Давайте рассмотрим следующую диаграмму, которая показывает общий поток управления обработкой исключений.

Исключения могут быть выброшены и пойманы с помощью блоков try
и catch
. Вы несете ответственность за выброс исключений, если что-то произойдет, чего не ожидается. Давайте быстро рассмотрим основной поток обработки исключений, как показано в следующем псевдокоде.
// code before the try-catch block try { // code // if something is not as expected // throw exception using the "throw" keyword // code, it won't be executed if the above exception is thrown } catch (Exception $e) { // exception is raised and it'll be handled here // $e->getMessage() contains the error message } // code after the try-catch block, will always be executed
В большинстве случаев, когда вы имеете дело с исключениями, вы в конечном итоге используете шаблон, как показано в приведенном выше фрагменте. Вы также можете использовать блок finally
вместе с блоками try
и catch
, но мы вернемся к этому позже в этой статье.
Блок try
- тот, который используется, когда вы подозреваете, что ваш код может генерировать исключение. Вы всегда должны обертывать такой код, используя try
и catch
.
Выброс исключения
Исключение может быть вызвано функцией, которую вы вызываете, или вы можете использовать ключевое слово throw
для выбрасывания исключения вручную. Например, вы можете проверить некоторый ввод перед выполнением любой операции и выбросить исключение, если данные недействительны.
Здесь важно отметить, что если вы выбросите исключение, но вы не определили блок catch
, который должен обрабатывать это исключение, это приведет к фатальной ошибке. Поэтому вам нужно убедиться, что вы всегда определяете блок catch
, если вы бросаете исключения в своем приложении.
Когда исключение попадает в блок catch
, объект Exception
содержит сообщение об ошибке, которое было выбрано с использованием ключевого слова throw
. Переменная $e
в приведенном выше примере является экземпляром класса Exception
, поэтому она имеет доступ ко всем методам этого класса. В этом блоке вы должны определить свою собственную логику обработки исключений - что именно вы хотите сделать с ошибкой, которую вы поймаете.
В следующем разделе мы рассмотрим пример из реального мира, чтобы понять, как работает обработка исключений.
Пример из реального мира
В этом разделе мы построим реальный пример для демонстрации обработки исключений в PHP.
Предположим, что вы создали приложение, которое загружает конфигурацию приложения из файла config.php. Теперь важно, чтобы файл config.php присутствовал, когда ваше приложение загружается. Таким образом, ваше приложение не может работать, если файл config.php отсутствует. Так что это идеальный случай, чтобы выбросить исключение и сообщить пользователю, что им необходимо исправить проблему.
<?php try { // init bootstrapping phase $config_file_path = "config.php"; if (!file_exists($config_file_path)) { throw new Exception("Configuration file not found."); } // continue execution of the bootstrapping phase } catch (Exception $e) { echo $e->getMessage(); die(); } ?>
Как вы можете видеть в приведенном выше примере, мы проверяем наличие файла config.php в начале фазы начальной загрузки. Если файл config.php найден, выполнение продолжается в обычном режиме. С другой стороны, мы выбросим исключение, если файл config.php не существует. Кроме того, мы хотели бы прекратить выполнение, если есть исключение!
Вот как вы можете использовать исключения в своих приложениях. Вы должны выбрасывать исключения для исключительных случаев использования - вы не должны излишне бросать исключения для ошибок, таких как недопустимые учетные данные пользователя, неправильные разрешения на доступ к каталогам и т. д., которые вы часто ожидаете. Они лучше обрабатываются общими сообщениями об ошибках в потоке выполнения обычного приложения.
Таким образом, это был пример обработки исключений с использованием класса Exception
по умолчанию. В следующем разделе мы рассмотрим, как вы можете расширить основной класс Exception
и создать свои собственные пользовательские исключения в своем приложении.
Как создавать пользовательские исключения
В этом разделе мы обсудим, как вы можете создавать пользовательские исключения в своих приложениях. Фактически, мы расширим пример, который мы только что обсуждали в предыдущем разделе, чтобы продемонстрировать пользовательские исключения.
В предыдущем примере мы выбрали исключение конфигурации, используя класс Exception
по умолчанию. Это прекрасно, если вы просто хотите иметь дело с сообщением об ошибке. Однако иногда вы хотите сделать немного больше в зависимости от типа исключения, которое бросается. Вот почему пользовательские исключения полезны.
Перейдем к предыдущему примеру, как показано в следующем фрагменте.
<?php class ConfigFileNotFoundException extends Exception {} try { // init bootstrapping phase $config_file_path = "config.php"; if (!file_exists($config_file_path)) { throw new ConfigFileNotFoundException("Configuration file not found."); } // continue execution of the bootstrapping phase } catch (ConfigFileNotFoundException $e) { echo "ConfigFileNotFoundException: ".$e->getMessage(); // other additional actions that you want to carry out for this exception die(); } catch (Exception $e) { echo $e->getMessage(); die(); } ?>
Во-первых, мы определили класс ConfigFileNotFoundException
, который расширяет основной класс Exception
. Теперь он становится нашим настраиваемым классом исключений, и мы можем использовать его, когда хотим выбросить исключение ConfigFileNotFoundException
в нашем приложении.
Затем мы использовали ключевое слово throw
для исключения исключений ConfigFileNotFoundException
в случае, если файл config.php не существует. Однако важное различие находится в блоке catch
. Как вы можете видеть, мы определили два блока catch
, и каждый блок используется для обнаружения различного типа исключения.
Первый получает исключения типа ConfigFileNotFoundException
. Итак, если генерируемое исключение относится к типу ConfigFileNotFoundException
, этот блок будет выполнен. Если тип исключения не соответствует какому-либо конкретному блоку catch
, он будет соответствовать последнему, который должен поймать все генерические сообщения об исключениях.
Блок Finally
В этом разделе мы рассмотрим, как вы можете использовать ключевое слово finally
вместе с блоками try
и catch
. Иногда вы хотите выполнить часть кода независимо от того, было ли исключено исключение. Вот где вы можете использовать блок finally
, поскольку код, который вы размещаете в блоке finally, всегда будет выполняться после выполнения блоков try и catch независимо от того, было ли выбрано исключение.
Попробуем понять это, используя следующий пример.
try { // code // if something is not as expected // throw exception using the "throw" keyword // code, it won't be executed if the above exception is thrown } catch (Exception $e) { // exception is raised and it'll be handled here // $e->getMessage() contains the error message } finally { // code, it'll always be executed }
Код в приведенном выше примере почти то же самое с единственным исключением, что мы добавили блок finally
после блока catch
. И, как мы обсуждали, код в этом блоке всегда будет выполняться.
Типичные прецеденты, которые мы могли бы придумать для использования блока finally, обычно связаны с очисткой ресурсов. Например, если вы открыли соединение с базой данных или файл на диске в блоке try
, вы можете выполнять задачи очистки, такие как закрытие соединения в блоке finally
, так как это гарантировано.
Обработка исключений - это ключевой навык кодирования, и вы должны подумать над тем, как будут обрабатываться исключения при разработке ваших приложений. Это поможет вам обнаружить и восстановить непредвиденные ошибки в вашем приложении. Надеюсь, что этот пост вдохновит вас написать лучший код обработки ошибок!
Заключение
Сегодня мы обсудили тему обработки исключений в PHP. В первой половине статьи мы обсудили основы исключений в PHP и создали реальный пример, чтобы продемонстрировать, как они работают. В конце мы рассмотрели, как вы можете создавать пользовательские исключения, расширяя основной класс Exception
.
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weeklyEnvato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post