📜 ⬆️ ⬇️

Throwable exception and php7 errors

In the past, handling fatal errors was almost impossible. The handler set by set_error_handler will not be called, the script will simply be completed.
In PHP 7, if fatal errors (E_ERROR) and fatal errors occur with the ability to handle (E_RECOVERABLE_ERROR), an exception will be thrown, and the script will not end. But certain errors, for example, “out of memory”, still lead to a halt. Missed errors in PHP 7 will be “fatal”, as well as in php 5. *.
Please note that other types of errors such as warinng and notice remain unchanged in php 7.

Exceptions thrown from E_ERROR and E_RECOVERABLE_ERROR are not inherited from Exception . This separation was made to prevent these errors from being processed by code written under 5. *. Exceptions for fatal errors are now an instance of a new class: Error . Like any other exceptions, the Error can be caught, processed, and executed by the finally block.
Throwable

Both classes, and Error and Exception implement the new Throwable interface.
The new exception hierarchy is as follows:
 interface Throwable |- Exception implements Throwable |- ... |- Error implements Throwable |- TypeError extends Error |- ParseError extends Error |- AssertionError extends Error 


If Throwable is defined in PHP 7 code, it looks like this:
 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; } 

This interface must be familiar. Throwable methods are almost identical to Exception methods. The only difference is that Throwable :: getPrevious () can return any instance of Throwable , and not just Exception . Exception and Error constructors accept any Throwable instance as the previous exception.
Throwable can be used in a try / catch block to catch both Exception and Error (and any other possible future exceptions). Remember that it is good practice to “catch” exceptions with a specific exception class and handle each type separately. But sometimes you want to catch any exception. In PHP 7, a try / catch block for all exceptions should use Throwable instead of Exception .
 try { // Code that may throw an Exception or Error. } catch (Throwable $t) { // Handle exception } 


User classes cannot implement Throwable . This was done for predictability: only Exception or Error instances can be thrown. In addition, exceptions contain information about where the object was created in the trace . User classes do not have the necessary parameters to store this information.
')
Error

Virtually all errors (E_ERROR, E_RECOVERABLE_ERROR) in PHP 5.x, in PHP 7 are thrown by the Error instance. Like any other exceptions, Error can be caught using a try / catch block.
 try { $undefined->method(); // Throws an Error object in PHP 7. } catch (Error $e) { // Handle error } 


Most of the errors that were “fatal” in PHP 5.x in PHP 7 will throw out simple Error objects, but some will throw out objects of subclasses: TypeError , ParseError and AssertionError .

Type error

A TypeError instance is thrown when the method arguments or return value does not match the declared type.

 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 is thrown when the include (by include / require ) file or code in eval contains syntax errors.
 try { require 'file-with-parse-error.php'; } catch (ParseError $e) { echo $e->getMessage(), "\n"; } 


AssertionError

When the condition specified by the assert () method is not met, AssertionError is thrown:
 ini_set('zend.assertions', 1); ini_set('assert.exception', 1); $test = 1; assert($test === 0); 

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

The assert () method is executed and AssertionError is thrown only if they are enabled in the settings: zend.assertions = 1 and assert.exception = 1 .

Using Error in your code

We can use the Error class, as well as expand the Error , by creating our own hierarchy of the Error class. This raises the question: which exception should throw an Exception , and which Error ?
Error should be used to indicate problems in the code that require the attention of the programmer (such as the wrong type of input data and syntax errors). Exception should be used when an exception can be "safely" processed, and program execution can continue.
Since Error objects cannot be processed during program execution, Error “catching” should be rare. In general, Error should be caught only to log them, the necessary "data cleansing", and display errors for the user.

We catch exceptions in both PHP 5.x and PHP 7

To catch exceptions in both php 5.x and php 7, using the same code, use several catch blocks, catch Throwable first, then Exception . After PHP 5.x support is not required, you can simply remove the catch block 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 } 

Source: https://habr.com/ru/post/261451/


All Articles