The getMessage() method of Throwable class is used to return a detailed message of the Throwable object which can also be null. One can use this method to get the detail message of exception as a string value. Syntax: public String getMessage()
The checkNum() function is called in a «try» block. The exception within the checkNum() function is thrown. The «catch» block retrieves the exception and creates an object ($e) containing the exception information. The error message from the exception is echoed by calling $e->getMessage() from the exception object.
As of PHP 7.1. 0, a catch block may specify multiple exceptions using the pipe ( | ) character. This is useful for when different exceptions from different class hierarchies are handled the same.
PHP supports using multiple catch blocks within try catch. This allows us to customize our code based on the type of exception that was thrown. This is useful for customizing how you display an error message to a user, or if you should potentially retry something that failed the first time.
The GetMessage function retrieves messages associated with the window identified by the hWnd parameter or any of its children, as specified by the IsChild function, and within the range of message values given by the wMsgFilterMin and wMsgFilterMax parameters.
Using printStackTrace() method − It print the name of the exception, description and complete stack trace including the line where exception occurred. Using toString() method − It prints the name and description of the exception. Using getMessage() method − Mostly used. It prints the description of the exception.
Java provides two different options to handle an exception. You can either use the try-catch-finally approach to handle all kinds of exceptions. Or you can use the try-with-resource approach which allows an easier cleanup process for resources.
Хотя PHP уже давно поддерживает обработку исключений, однако, по сравнению с Java эта поддержка была довольно слабой
Первоначальная поддержка обработки исключений была введена в язык с 5 версии PHP, с двумя простыми встроенными классами исключений — Exception и ErrorException, с поддержкой дополнительных классов через SPL. Идея этого поста состоит в том, чтобы представить читателям современные возможности обработки исключений PHP.
Новый интерфейс
Хотя PHP 7 предоставляет классы Error и Exception, давайте сначала затронем интерфейс Throwable . И Error и Exception классы реализуют Throwable интерфейс — это основа для любого объекта , который может быть брошен с помощью оператора throw. Единственное, что он не может быть реализован непосредственно в классах пользовательского пространства, только через расширение класса Exception. Кроме того, он обеспечивает единую точку для отлова обоих типов ошибок в одном выражении:
<?php
try {
// ваш код
} catch (Throwable $e) {
echo 'Очень хороший способ отловить исключения и ошибки';
}
Список доступных встроенных классов исключений начиная с PHP 7.4:
- Exception
- ErrorException
- Error
- ArgumentCountError
- ArithmeticError
- AssertionError
- DivisionByZeroError
- CompileError
- ParseError
- TypeError
Дополнительные классы исключений можно найти в стандартной библиотеке PHP . И наиболее заметным из расширений JSON является класс JsonException.
THROWABLE
Интерфейс Throwable PHP 7:
interface Throwable
{
public function getMessage(): string; // Error reason
public function getCode(): int; // Error code
public function getFile(): string; // Error begin file
public function getLine(): int; // Error begin line
public function getTrace(): array; // Return stack trace as array like debug_backtrace()
public function getTraceAsString(): string; // Return stack trace as string
public function getPrevious(): Throwable; // Return previous `Trowable`
public function __toString(): string; // Convert into string
}
Вот иерархия Throwable:
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
Ошибка, почему?
В предыдущих версиях PHP ошибки обрабатывались совершенно иначе, чем исключения. Если возникала ошибка, то пока она не была фатальной, она могла быть обработана пользовательской функцией.
Проблема заключалась в том, что было несколько фатальных ошибок, которые не могли быть обработаны определяемым пользователем обработчиком ошибок. Это означало, что вы не могли корректно обрабатывать фатальные ошибки в PHP. Было несколько побочных эффектов, которые были проблематичными, такие как потеря контекста времени выполнения, деструкторы не вызывались, да и вообще иметь дело с ними было неудобно. В PHP 7 фатальные ошибки теперь являются исключениями, и мы можем легко их обработать. Фатальные ошибки приводят к возникновению исключений. Вам необходимо обрабатывать нефатальные ошибки с помощью функции обработки ошибок.
Вот пример ловли фатальной ошибки в PHP 7.1. Обратите внимание, что нефатальная ошибка не обнаружена.
<?php
try {
// будет генерировать уведомление, которое не будет поймано
echo $someNotSetVariable;
// фатальная ошибка, которая сейчас на самом деле ловится
someNoneExistentFunction();
} catch (Error $e) {
echo "Error caught: " . $e->getMessage();
}
Этот скрипт выведет сообщение об ошибке при попытке доступа к недопустимой переменной. Попытка вызвать функцию, которая не существует, приведет к фатальной ошибке в более ранних версиях PHP, но в PHP 7.1 вы можете ее перехватить. Вот вывод для скрипта:
Notice: Undefined variable: someNotSetVariable on line 3
Error caught: Call to undefined function someNoneExistentFunction()
Константы ошибок
В PHP много констант, которые используются в отношении ошибок. Эти константы используются при настройке PHP для скрытия или отображения ошибок определенных классов.
Вот некоторые из наиболее часто встречающихся кодов ошибок:
- E_DEPRECATED — интерпретатор сгенерирует этот тип предупреждений, если вы используете устаревшую языковую функцию. Сценарий обязательно продолжит работать без ошибок.
- E_STRICT — аналогично E_DEPRECATED, — указывает на то, что вы используете языковую функцию, которая не является стандартной в настоящее время и может не работать в будущем. Сценарий будет продолжать работать без каких-либо ошибок.
- E_PARSE — ваш синтаксис не может быть проанализирован, поэтому ваш скрипт не запустится. Выполнение скрипта даже не запустится.
- E_NOTICE — движок просто выведет информационное сообщение. Выполнение скрипта не прервется, и ни одна из ошибок не будет выдана.
- E_ERROR — скрипт не может продолжить работу, и завершится. Выдает ошибки, а как они будут обрабатываться, зависит от обработчика ошибок.
- E_RECOVERABLE_ERROR — указывает на то, что, возможно, произошла опасная ошибка, и движок работает в нестабильном состоянии. Дальнейшее выполнение зависит от обработчика ошибок, и ошибка обязательно будет выдана.
Полный список констант можно найти в руководстве по PHP.
Функция обработчика ошибок
Функция set_error_handler() используется, чтобы сообщить PHP как обрабатывать стандартные ошибки, которые не являются экземплярами класса исключений Error. Вы не можете использовать функцию обработчика ошибок для фатальных ошибок. Исключения ошибок должны обрабатываться с помощью операторов try/catch. set_error_handler() принимает callback функцию в качестве своего параметра. Callback-функции в PHP могут быть заданы двумя способами: либо строкой, обозначающей имя функции, либо передачей массива, который содержит объект и имя метода (именно в этом порядке). Вы можете указать защищенные и приватные методы для callable в объекте. Вы также можете передать значение null, чтобы указать PHP вернуться к использованию стандартного механизма обработки ошибок. Если ваш обработчик ошибок не завершает программу и возвращает результат, ваш сценарий будет продолжать выполняться со строки, следующей за той, где произошла ошибка.
PHP передает параметры в вашу функцию обработчика ошибок. Вы можете опционально объявить их в сигнатуре функции, если хотите использовать их в своей функции.
Вот пример:
<?php
function myCustomErrorHandler(int $errNo, string $errMsg, string $file, int $line) {
echo "Ух ты, мой обработчик ошибок получил #[$errNo] в [$file] на [$line]: [$errMsg]";
}
set_error_handler('myCustomErrorHandler');
try {
why;
} catch (Throwable $e) {
echo 'И моя ошибка: ' . $e->getMessage();
}
Если вы запустите этот код в PHP-консоли php -a, вы должны получить похожий вывод:
Error #[2] occurred in [php shell code] at line [3]: [Use of undefined constant why - assumed 'why' (this will throw an Error in a future version of PHP)]
Самые известные PHP библиотеки , которые делают обширное использование РНР set_error_handler() и могут сделать хорошие представления исключений и ошибок являются whoops, и Symony Debug, ErrorHandler компоненты. Я смело рекомендую использовать один из них. Если не собираетесь их использовать в своем проекте, то вы всегда можете черпать вдохновение из их кода. В то время как компонент Debug широко используется в экосистеме Symfony, Whoops остается библиотекой выбора для фреймворка Laravel .
Для подробного и расширенного использования, пожалуйста, обратитесь к руководству по PHP для обработчика ошибок.
Отображение или подавление нефатальной ошибки
Когда ваше приложение выходит в продакшн, логично, что вы хотите скрыть все системные сообщения об ошибках во время работы, и ваш код должен работать без генерации предупреждений или сообщений. Если вы собираетесь показать сообщение об ошибке, убедитесь, что оно сгенерировано и не содержит информации, которая может помочь злоумышленнику проникнуть в вашу систему.
В вашей среде разработки вы хотите, чтобы все ошибки отображались, чтобы вы могли исправить все проблемы, с которыми они связаны, но в процессе работы вы хотите подавить любые системные сообщения, отправляемые пользователю.
Для этого вам нужно настроить PHP, используя следующие параметры в вашем файле php.ini:
- display_errors – может быть установлен в false для подавления сообщений
- log_errors – может использоваться для хранения сообщений об ошибках в файлах журнала
- error_reporting – можно настроить, какие ошибки вызывают отчет
Лучше всего корректно обрабатывать ошибки в вашем приложении. В производственном процессе вы должны скорее регистрировать необработанные ошибки, чем разрешать их отображение пользователю. Функция error_log() может использоваться для отправки сообщения одной из определенных процедур обработки ошибок. Вы также можете использовать функцию error_log() для отправки электронных писем, но лично вы бы предпочли использовать хорошее решение для регистрации ошибок и получения уведомлений при возникновении ошибок, например Sentry или Rollbar .
Существует вещь, называемая оператором контроля ошибок ( @ ), который по своей сути может игнорировать и подавлять ошибки. Использование очень простое — просто добавьте любое выражение PHP с символом «собаки», и сгенерированная ошибка будет проигнорирована. Хотя использование этого оператора может показаться интересным, я призываю вас не делать этого. Мне нравится называть это живым пережитком прошлого.
Больше информации для всех функций, связанных с ошибками PHP, можно найти в руководстве.
Исключения (Exceptions)
Исключения являются основной частью объектно-ориентированного программирования и впервые были представлены в PHP 5.0. Исключением является состояние программы, которое требует специальной обработки, поскольку оно не выполняется ожидаемым образом. Вы можете использовать исключение, чтобы изменить поток вашей программы, например, чтобы прекратить что-либо делать, если некоторые предварительные условия не выполняются.
Исключение будет возникать в стеке вызовов, если вы его не перехватите. Давайте посмотрим на простой пример:
try {
print "это наш блок попыток n";
throw new Exception();
} catch (Exception $e) {
print "что-то пошло не так, есть улов!";
} finally {
print "эта часть всегда выполняется";
}
PHP включает в себя несколько стандартных типов исключений, а стандартная библиотека PHP (SPL) включает в себя еще несколько. Хотя вам не нужно использовать эти исключения, это означает, что вы можете использовать более детальное обнаружение ошибок и отчеты. Классы Exception и Error реализуют интерфейс Throwable и, как и любые другие классы, могут быть расширены. Это позволяет вам создавать гибкие иерархии ошибок и адаптировать обработку исключений. Только класс, который реализует класс Throwable, может использоваться с ключевым словом throw. Другими словами, вы не можете объявить свой собственный базовый класс и затем выбросить его как исключение.
Надежный код может встретить ошибку и справиться с ней. Разумная обработка исключений повышает безопасность вашего приложения и облегчает ведение журнала и отладку. Управление ошибками в вашем приложении также позволит вам предложить своим пользователям лучший опыт. В этом разделе мы рассмотрим, как отлавливать и обрабатывать ошибки, возникающие в вашем коде.
Ловля исключений
Вы должны использовать try/catch структуру:
<?php
class MyCustomException extends Exception { }
function throwMyCustomException() {
throw new MyCustomException('Здесь что-то не так.');
}
try {
throwMyCustomException();
} catch (MyCustomException $e) {
echo "Ваше пользовательское исключение поймано";
echo $e->getMessage();
} catch (Exception $e) {
echo "Стандартное исключение PHP";
}
Как видите, есть два предложения catch. Исключения будут сопоставляться с предложениями сверху вниз, пока тип исключения не будет соответствовать предложению catch. Эта очень простая функция throwMyCustomException() генерирует исключение MyCustomException, и мы ожидаем, что оно будет перехвачено в первом блоке. Любые другие исключения, которые произойдут, будут перехвачены вторым блоком. Здесь мы вызываем метод getMessage() из базового класса Exception. Вы можете найти больше информации о дополнительном методе в Exception PHP docs.
Кроме того, можно указать несколько исключений, разделяя их трубой ( | ).
Давайте посмотрим на другой пример:
<?php
class MyCustomException extends Exception { }
class MyAnotherCustomException extends Exception { }
try {
throw new MyAnotherCustomException;
} catch (MyCustomException | MyAnotherCustomException $e) {
echo "Caught : " . get_class($e);
}
Этот очень простой блок catch будет перехватывать исключения типа MyCustomException и MyAnotherCustomException.
Немного более продвинутый сценарий:
// exceptions.php
use SymfonyComponentHttpKernelExceptionNotFoundHttpException;
try {
throw new NotFoundHttpException();
} catch (Exception $e) {
echo 1;
} catch (NotFoundHttpException $e) {
echo 2;
} catch (Exception $e) {
echo 3;
} finally {
echo 4;
}
Это ваш окончательный ответ?
В PHP 5.5 и более поздних, блок finally также может быть указан после или вместо блоков catch. Код внутри блока finally всегда будет выполняться после блоков try и catch независимо от того, было ли выброшено исключение, и до возобновления нормального выполнения. Одним из распространенных применений блока finally является закрытие соединения с базой данных, но, наконец, его можно использовать везде, где вы хотите, чтобы код всегда выполнялся.
<?php
class MyCustomException extends Exception { }
function throwMyCustomException() {
throw new MyCustomException('Здесь что-то не так');
}
try {
throwMyCustomException();
} catch (MyCustomException $e) {
echo "Ваше пользовательское исключение поймано ";
echo $e->getMessage();
} catch (Exception $e) {
echo "Стандартное исключение PHP";
} finally {
echo "Я всегда тут";
}
Вот хороший пример того, как работают операторы PHP catch/finally:
<?php
try {
try {
echo 'a-';
throw new exception();
echo 'b-';
} catch (Exception $e) {
echo 'пойманный-';
throw $e;
} finally {
echo 'завершенный-';
}
} catch (Exception $e) {
echo 'конец-';
}
Функция обработчика исключений
Любое исключение, которое не было обнаружено, приводит к фатальной ошибке. Если вы хотите изящно реагировать на исключения, которые не перехватываются в блоках перехвата, вам нужно установить функцию в качестве обработчика исключений по умолчанию.
Для этого вы используете функцию set_exception_handler() , которая принимает вызываемый элемент в качестве параметра. Ваш сценарий завершится после того, как вызов будет выполнен.
Функция restore_exception_handler() вернет обработчик исключений к его предыдущему значению.
<?php
class MyCustomException extends Exception { }
function exception_handler($exception) {
echo "Uncaught exception: " , $exception->getMessage(), "n";
}
set_exception_handler('exception_handler');
try {
throw new Exception('Uncaught Exception');
} catch (MyCustomException $e) {
echo "Ваше пользовательское исключение поймано ";
echo $e->getMessage();
} finally {
echo "Я всегда тут";
}
print "Не выполнено";
Здесь простая функция exception_handler будет выполняться после блока finally, когда ни один из типов исключений не был сопоставлен. Последний вывод никогда не будет выполнен.
Для получения дополнительной информации обратитесь к документации PHP.
Старый добрый «T_PAAMAYIM_NEKUDOTAYIM»
Вероятно, это было самое известное сообщение об ошибке PHP. В последние годы было много споров по этому поводу. Вы можете прочитать больше в отличном сообщении в блоге от Фила Осетра .
Сегодня я с гордостью могу сказать, что если вы запустите этот код с PHP 7, то сообщение о T_PAAMAYIM_NEKUDOTAYIM больше не будет:
<?php
class foo
{
static $bar = 'baz';
}
var_dump('foo'::$bar);
// Output PHP < 7.0:
// PHP Parse error: syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM) in php shell code on line 1
// Output PHP > 7.0:
// string(3) "baz"
?>
В заключении
Со времени первого внедрения обработки исключений в PHP прошло много лет, пока мы не получили гораздо более надежную и зрелую обработку исключений, чем в Java. Обработка ошибок в PHP 7 получила много внимания, что делает его хорошим, открывая пространство для будущих улучшений, если мы действительно с сегодняшней точки зрения нуждаемся в них.
The new interface
While PHP 7 provides both Error and Exception classes, let’s check the Throwable interface first. Both Error and Exception classes implement Throwable interface – it’s a basis for any object that can be thrown via throw statement. It only has one exception to notice, it cannot be implemented in userland classes directly, but only through extending the Exception class. Also, it provides a single point for catching both types of error in a single statement:
<?php
try {
// your code
} catch (Throwable $e) {
echo 'Very nice way to catch Exception and Error exceptions';
}
List of available built-in exception classes since PHP 7.4:
- Exception
- ErrorException
- Error
- ArgumentCountError
- ArithmeticError
- AssertionError
- DivisionByZeroError
- CompileError
- ParseError
- TypeError
More Exception classes can be found inside PHP’ Standard Library. And the most notable one that comes from the JSON extension is the JsonException class.
Error, what?
In previous versions of PHP, errors were treated quite differently than exceptions. An error was something that was produced in the engine and as long as it was not fatal, it could be handled by a user-defined function.
The problem was that there were several errors that were fatal and that could not be handled by a user-defined error handler. This meant that you couldn’t handle fatal errors in PHP gracefully. There were several side-effects that were problematic, such as the loss of runtime context, destructors would not be called and dealing with them was clunky. In PHP 7, fatal errors are now exceptions and we can handle them very easily. Fatal errors result in an error exception being thrown. You need to handle non-fatal errors with an error-handling function.
Here is an example of catching a fatal error in PHP 7.1. Notice how the non-fatal error is not caught.
<?php
try {
// this will generate notice that would not be caught
echo $someNotSetVariable;
// fatal error that now actually is caught
someNoneExistentFunction();
} catch (Error $e) {
echo "Error caught: " . $e->getMessage();
}
This script will output a notice error for the attempt to access an invalid variable. Trying to call a function that does not exist would result in a fatal error in earlier versions of PHP, but in PHP 7.1 you can catch it. Here is the output for the script:
Notice: Undefined variable: someNotSetVariable on line 3
Error caught: Call to undefined function someNoneExistentFunction()
Error constants
PHP has a lot of constants that are used in relation to errors. These constants are used when configuring PHP to hide or display errors of certain classes.
Here are some of the most commonly seen error codes:
- E_DEPRECATED – the interpreter will generate this type of warnings if you use a deprecated language feature. The script will definitely continue to run without errors.
- E_STRICT – similar to E_DEPRECATED, this indicates that you are using a language feature that is not standard currently and might not work in the future. The script will continue to run without any errors thrown.
- E_PARSE – your syntax could not be parsed so your script won’t start. Script execution will not even start.
- E_NOTICE – the engine will just print out an informational message. Script execution won’t break and none of the errors will be thrown.
- E_ERROR – the script cannot continue running and it is being terminated. Will throw errors and how these are going to be handled depends on the error handler.
- E_RECOVERABLE_ERROR – it indicates that a probably dangerous error occurred, but did not leave the Engine in an unstable state. Further execution depends on the error handler and error will definitely be thrown.
For full list of constants please consult the PHP manual.
Error handler function
The set_error_handler() function is used to tell PHP how to handle standard engine errors that are not instances of the Error exception class. You cannot use an error-handler function for fatal errors. Error exceptions must be handled with try/catch statements. set_error_handler() accepts a callable as its parameter. Callables in PHP can be specified in two ways: either by a string denoting the name of a function or by passing an array that contains an object and the name of a method (in that order). You can specify protected and private methods as the callable in an object. You can also pass null to tell PHP to revert to the usage of the standard error-handling mechanism. If your error handler does not terminate the program and returns, your script will continue executing at the line after the one where the error occurred.
PHP passes parameters to your error-handler function. You can optionally declare these in the function signature if you want to use them in your function.
Here is an example of custom:
<?php
function myCustomErrorHandler(int $errNo, string $errMsg, string $file, int $line) {
echo "Wow my custom error handler got #[$errNo] occurred in [$file] at line [$line]: [$errMsg]";
}
set_error_handler('myCustomErrorHandler');
try {
what;
} catch (Throwable $e) {
echo 'And my error is: ' . $e->getMessage();
}
If you run this code in PHP console php -a you should receive similar output:
Error #[2] occurred in [php shell code] at line [3]: [Use of undefined constant what - assumed 'what' (this will throw an Error in a future version of PHP)]
The most prominent PHP libraries that do extensive usage of PHP’s set_error_handler() and can do nice representations of exceptions and error are Whoops or Symony’s Debug and ErrorHandler components. My suggestion is to use one of those. If not, you can always draw inspiration from their code. While Debug component has extensive usage within the Symfony ecosystem, Whoops remains library of choice for Laravel framework.
For detailed and advanced usage, please consult PHP manual on error handler.
Displaying or suppressing the non-fatal error message
When you application reaches production, you want to hide all system error messages while in production and your code must run without generating warnings or messages. If you are going to show an error message, make sure that it is the one you’ve generated and that it does not include information that could help an attacker break into your system.
In your development environment, you want all errors to be displayed so that you can fix all the issues they relate to, but while in production, you want to suppress any system messages being sent to the user.
To accomplish this, you need to configure PHP using the following settings in your php.ini file:
- display_errors – can be set to false to suppress messages
- log_errors – can be used to store error messages in log files
- error_reporting – can be set to configure which errors trigger a report
The best practice is to handle errors in your application gracefully. In production, you should rather log unhandled errors instead of allowing them to be displayed to the user. The error_log() function can be used to send a message to one of the defined error handling routines. You can also use the error_log() function to send emails, but personally, would rather use a good solution for logging errors and receiving notifications when an error occurs like Sentry or Rollbar.
There is a thing called Error Control Operator – the at-sign (@) – that in the essence can ignore and suppress errors. The usage is very easy – just prepend any PHP expression with at-sign and generated error will be ignored. Although using this operator may look interesting, I urge you not to do that. I like to call it the living relict from the past.
More information for all PHP error related function can be found in manual.
Exceptions
Exceptions are a core part of object-oriented programming and were first introduced in PHP 5.0. An exception is a program state that requires special processing because it’s not running in an expected manner. You can use an exception to change the flow of your program, for example, to stop doing something if certain preconditions are not met.
An exception will bubble up through the call stack if you do not catch it. Let’s check a simple example:
try {
print "this is our try block n";
throw new Exception();
} catch (Exception $e) {
print "something went wrong, caught yah!";
} finally {
print "this part is always executed n";
}
PHP includes several standard exception types, and the standard PHP library (SPL) includes a few more. Although you don’t have to use these exceptions, doing so means you can use more fine-grained error detection and report. The Exception and Error classes both implement the Throwable interface and, like any other classes, can be extended. This allows you to create flexible error hierarchies and tailor your exception handling. Only a class that implements the Throwable class can be used with the throw keyword. In other words, you can’t declare your own base class and then throw it as an exception.
Robust code can encounter an error and cope with it. Handling exceptions in a sensible way improves the security of your application and makes logging and debugging easier. Managing errors in your application will also allow you to offer your users a better experience. In this section, we cover how to trap and handle errors that occur in your code.
Catching exceptions
Let’s look at this simple example:
<?php
class MyCustomException extends Exception { }
function throwMyCustomException() {
throw new MyCustomException('There is something wrong.');
}
try {
throwMyCustomException();
} catch (MyCustomException $e) {
echo "Your custom exception caught ";
echo $e->getMessage();
} catch (Exception $e) {
echo "PHP base exception caught";
}
As you can see, there are two catch clauses. Exceptions will be matched against the clauses from top to bottom until the type of exception matches the catch clause. This very simple throwMyCustomException() function throws MyCustomException and we expect it to be caught in the first block. Any other exceptions that will occur will be caught by the second block. Here we are calling getMessage() method from the base Exception class. You can find more information about additional method in Exception PHP docs.
You can also specify multiple exceptions by separating them with a pipe (|) character.
Let’s look at another example:
<?php
class MyCustomException extends Exception { }
class MyAnotherCustomException extends Exception { }
try {
throw new MyAnotherCustomException;
} catch (MyCustomException | MyAnotherCustomException $e) {
echo "Caught : " . get_class($e);
}
This very simple catch block will catch exceptions of type MyCustomException and MyAnotherCustomException.
A bit more advanced catching scenario:
// exceptions.php
use SymfonyComponentHttpKernelExceptionNotFoundHttpException;
try {
throw new NotFoundHttpException();
} catch (Exception $e) {
echo 1;
} catch (NotFoundHttpException $e) {
echo 2;
} catch (Exception $e) {
echo 3;
} finally {
echo 4;
}
Is this your final answer?
In PHP 5.5 and later, a finally block may also be specified after or instead of catch blocks. Code within the finally block will always be executed after the try and catch blocks, regardless of whether an exception has been thrown, and before normal execution resumes. One common use for the finally block is to close a database connection, but finally can be used wherever you want code to always be executed.
<?php
class MyCustomException extends Exception { }
function throwMyCustomException() {
throw new MyCustomException('There is something wrong.');
}
try {
throwMyCustomException();
} catch (MyCustomException $e) {
echo "Your custom exception caught ";
echo $e->getMessage();
} catch (Exception $e) {
echo "PHP base exception caught";
} finally {
echo "I'm always here";
}
Here is one good example to be in line with how PHP’s catch/finally statements work:
<?php
try {
try {
echo 'a-';
throw new exception();
echo 'b-';
} catch (Exception $e) {
echo 'caught-';
throw $e;
} finally {
echo 'finished-';
}
} catch (Exception $e) {
echo 'end-';
}
Exception handler function
Any exception that is not caught results in a fatal error. If you want to respond gracefully to exceptions that are not caught in catch blocks, you’ll need to set a function as the default exception handler.
To do so, you use the set_exception_handler() function, which accepts a callable as its parameter. Your script will terminate after the callable has executed.
The function restore_exception_handler() will revert the exception handler to its previous value.
<?php
class MyCustomException extends Exception { }
function exception_handler($exception) {
echo "Uncaught exception: " , $exception->getMessage(), "n";
}
set_exception_handler('exception_handler');
try {
throw new Exception('Uncaught Exception');
} catch (MyCustomException $e) {
echo "Your custom exception caught ";
echo $e->getMessage();
} finally {
echo "I'm always here";
}
print "Not executed";
Here the simple exception_handler function will be executed after finally block when none of the exception types was matched. The last print statement will never be executed.
For more info consult PHP docs.
The good old “T_PAAMAYIM_NEKUDOTAYIM”
This was probably the most famous PHP error message ever. There has been much controversy about it in recent years. You can read more in an excellent blog post from Phil Sturgeon.
Today I can proudly say if you run this code with PHP 7 no T_PAAMAYIM_NEKUDOTAYIM will occur:
<?php
class foo
{
static $bar = 'baz';
}
var_dump('foo'::$bar);
// Output PHP < 7.0:
// PHP Parse error: syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM) in php shell code on line 1
// Output PHP > 7.0:
// string(3) "baz"
?>
Conclusion
Since the first introduction of exception handling to PHP, many years have passed until we ended up with much more solid and matured exceptional handling that Java had, quite frankly for ages. Error handling in PHP 7 received much attention making it solid good, opening space for future improvements if we actually from today’s perspective need one.