Throwable exception и ошибки в php7

от автора

В прошлом, обрабатывать фатальные ошибки было практически невозможно. Обработчик, установленный set_error_handler вызван не будет, скрипт просто будет завершен.
В PHP 7 при возникновении фатальных ошибок (E_ERROR) и фатальных ошибок с возможностью обработки (E_RECOVERABLE_ERROR) будет выброшен exception, а не произойдет завершение скрипта. Но определенные ошибки, например «out of memory», по прежнему приведут к остановке. Не перехваченные ошибки в PHP 7, будут «фатальны», так же как и в php 5.*.

Обратите внимание, что другие виды ошибок, такие как warinng и notice остаются без изменения в php 7.

Исключения выброшенные из E_ERROR и E_RECOVERABLE_ERROR не наследуются от Exception. Это разделение было сделано, чтобы предотвратить обработку этих ошибок кодом, написанным под 5.*. Исключения для фатальных ошибок теперь являются экземпляром нового класса: Error. Как и любые другие исключения, Error может отловлен, обработан и выполнен finally блок.

Throwable

Оба класса, и Error и Exception реализуют новый интерфейс Throwable.
Новая иерархия исключения состоит в следующем:

interface Throwable     |- Exception implements Throwable         |- ...     |- Error implements Throwable         |- TypeError extends Error         |- ParseError extends Error         |- AssertionError extends Error 

Если Throwable определить в коде PHP 7, то выглядит это так:

interface Throwable {     public function getMessage(): string;     public function getCode(): int;     public function getFile(): string;     public function getLine(): int;     public function getTrace(): array;     public function getTraceAsString(): string;     public function getPrevious(): Throwable;     public function __toString(): string; } 

Этот интерфейс должен быть знаком. Методы Throwable практически идентичны метода Exception. Разница лишь в том, что Throwable::getPrevious() может вернуть любой экземпляр Throwable, а не просто Exception. Конструкторы Exception и Error принимают любой экземпляр Throwable как предыдущее исключение.
Throwable может быть использован в блоке try/catch для отлова и Exception и Error (и любых других возможных в будущем исключений). Помните, что хорошей практикой является «ловля» исключений определенным классом исключений и обработка каждого типа отдельно. Но и иногда требуется отлавливать любое исключение. В PHP 7 try/catch блок для всех исключений должен использовать Throwable вместо Exception.

try {     // Code that may throw an Exception or Error. } catch (Throwable $t) {     // Handle exception } 

Пользовательские классы не могут реализовывать Throwable. Это было сделано для предсказуемости: только экземпляры Exception или Error могут быть брошены. Кроме того, исключения содержать информацию о том, где объект был создан в stack trace. В пользовательских классах нет необходимых параметров, для хранения этой информации.

Error

Практически все ошибки (E_ERROR, E_RECOVERABLE_ERROR) в PHP 5.x, в PHP 7 выбрасывается экземпляром Error. Как и любые другие исключения, Error может быть пойман используя try/catch блок.

try {     $undefined->method(); // Throws an Error object in PHP 7. } catch (Error $e) {     // Handle error } 

Большинство ошибок, которые были «фатальны» в PHP 5.x в PHP 7 буду выбрасывать просты Error объекты, но некоторые будут выбрасывать объекты подклассов: TypeError, ParseError и AssertionError.

TypeError

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

function add(int $left, int $right) {     return $left + $right; }  try {     $value = add('left', 'right'); } catch (TypeError $e) {     echo $e->getMessage(), "\n"; }  //Result: //Argument 1 passed to add() must be of the type integer, string given 
ParseError

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

try {     require 'file-with-parse-error.php'; } catch (ParseError $e) {     echo $e->getMessage(), "\n"; } 
AssertionError

Когда условие, заданное методом assert() не выполняется, выбрасывается AssertionError:

ini_set('zend.assertions', 1); ini_set('assert.exception', 1);  $test = 1;  assert($test === 0); 

Fatal error: Uncaught AssertionError: assert($test === 0) 

Метод assert() выполняется и выбрасывается AssertionError только, если они включены в настройках: zend.assertions = 1 и assert.exception = 1.

Использование Error в своём коде

Мы можем использовать класс Error, а также расширить Error, создав собственную иерархию класса Error. Это порождает вопрос: какие исключение должен выбрасывать Exception, а какие Error?
Error должен использоваться для указания проблем в коде, требующих внимания программиста (такие как неправильный тип входящих данных и синтаксические ошибки). Exception должен использоваться, когда исключение может «безопасно» обработаться, и выполнение программы может продолжиться.
Поскольку, объекты Error не могут быть обработаны во время выполнения программы, «ловля» Error должна быть редкостью. В целом, Error должны быть пойманы только для логирования их, необходимой «чистки данных», и отображения ошибки для пользователя.

Ловим исключения и в PHP 5.x и в PHP 7

Чтобы поймать исключения и в php 5.x и в php 7 используя один код, используем несколько блоков catch, ловим Throwable первым, затем Exception. После того, как поддержка PHP 5.x не потребуется, можно просто удалить блок ловли Exception.

try {     // Code that may throw an Exception or Error. } catch (Throwable $t) {     // Executed only in PHP 7, will not match in PHP 5.x } catch (Exception $e) {     // Executed only in PHP 5.x, will not be reached in PHP 7 } 

ссылка на оригинал статьи http://habrahabr.ru/post/261451/


Комментарии

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *