Ideally in any programming language to catch errors you must wrap your code in a try-catch block or depending in the language you can report the errors with other mechanisms.
However in PHP as we know there are two types of errors, the traditional errors which are instances of the Error class. To report these errors we have to write a custom error handler or by checking for errors directly. Examples of these errors ArithmeticError, ParseError, TypeError, etc.
The other types of errors is the exceptions which extends the Exception class and can be easily caught using try-catch blocks.
In PHP 5 code the try-catch blocks only works with exceptions but trying to catch any other error related to the base Error class requires that we define a custom error handler using php set_error_handler() function.
For example:
// php 5 code function sum($a, $b) { return $a + $b; } try { $result = sum("a", "b"); echo $result; } catch (Exception $e) { echo "Error: " . $e->getMessage(); }
This code not caught in the try block and will show a TypeError:
PHP Fatal error: Uncaught TypeError: Unsupported operand types: string + string
With the release of PHP 7 to generalize the error reporting so we can catch all types of errors using both Error and Exception most errors are now reported by throwing Error exceptions.
With this in mind we can catch specific errors like so:
try { // Throws an Error object in PHP 7. } catch (Error $e) { // Handle error }
try { require 'file-with-parse-error.php'; } catch (ParseError $e) { echo $e->getMessage(), "\n"; }
try { // Code that may throw an Exception or ArithmeticError. } catch (ArithmeticError | Exception $e) { // show error message }
In addition to that a new interface introduced, the Throwable interface. Throwable is the base interface for any object that can be thrown via a throw
statement, including Error and Exception.Â
So now we can catch all types of errors using Throwable. By modifying the previous example to use throwable:
try { $result = sum("a", "b"); echo $result; } catch (\Throwable $e) { echo "Error: " . $e->getMessage(); } catch (\Exception $e) { echo "Error: " . $e->getMessage(); }
Output:
Error: Unsupported operand types: string + string
As you Throwable at the top of the exception class hierarchy and all exception types now implement Throwable.
Throwable Terminology
interface Throwable { /* Methods */ public getMessage(): string public getCode(): int public getFile(): string public getLine(): int public getTrace(): array public getTraceAsString(): string public getPrevious(): ?Throwable abstract public __toString(): string }
As you see the Throwable interface structure is the same as the Exception class but the difference is that Throwable::getPrevious()
can return any instance of Throwable
instead of Exception
We mentioned above that Throwable is an interface however you can’t implement it directly, and doing so will result in this error:
PHP Fatal error: Class myCustomException cannot implement interface Throwable, extend Exception or Error instead
As the error say to implement Throwable you have to create another interface which implement Throwable and then create another class which extend Exception and implement the custom interface like so:
interface MyCustomThrowable extends \Throwable { } class MyCustomException extends \Exception implements MyCustomThrowable { }
We can use this class to catch all types of errors:
try { throw new MyCustomException("System error"); } catch (MyCustomException $e) { echo $e->getMessage(); }