Php try catch finally

Php try catch finally

Представляем вашему вниманию руководство для новичков о том, как использовать блоки в PHP try catch . В этой статье я покажу, как перехватывать исключения.

Давайте сразу взглянем на пример сгенерированного исключения ( и впоследствии перехваченного ):

В приведенном выше примере я продемонстрировал использование TRY и CATCH , в котором исключение всегда сгенерировано ( только ради примера ):

  1. Внутри блока TRY мы проверяем, равняется ли цифра 1 цифре 2 . Так как она не равняется ( и никогда не будет равняться ), мы генерируем исключение с сообщением “ 1 не равняется 2! ”;
  2. Внутри блока CATCH мы перехватываем исключение и выводим соответствующее сообщение.
  • TRY : внутри блока PHP try мы задаем логику приложения. Этот блок содержит код, который может или не может сгенерировать исключение;
  • CATCH : блок CATCH будет перехватывать любые исключения, проявившиеся в предыдущем блоке TRY . Код внутри блока CATCH будет исполнен только в случае обнаружения исключения;
  • FINALLY : если вы используете PHP 5.5 и выше, то вы можете использовать блок FINALLY . Расположенный в нем код исполняется всегда, вне зависимости от того, было ли обнаружено исключение.

Когда используются исключения?

Исключения используются, когда результат операции отличается от того, что ожидало ваше приложение. К примеру, если ваше приложение пытается прочитать CSV-файл на сервере, а этого файла не существует, то можно сгенерировать исключение. Использование PHP try catch в примере:

В приведенном выше примере использования в PHP try exception мы генерируем исключение тогда, когда не можем открыть запрашиваемый файл. И генерируем мы его, так как файл должен был существовать. Примеры ситуаций, когда вы можете генерировать исключения:

  1. Ваше PHP-приложение не может подключиться к MySQL ;
  2. Ошибка при запросе к базе данных;
  3. Ошибка при запросе к API ;
  4. Получен некорректный тип запроса;
  5. Отсутствуют необходимые переменные $_POST или $_GET .

Нужно ли перехватывать все исключения?

Лично я так не считаю. К примеру: вам не удается подключиться к базе данных, и генерируется исключение, нужно ли тогда исполнять весь оставшийся код? Если весь последующий код привязан к базе данных, которой просто не существует, то зачем же его исполнять?

По моему мнению, исключения нужно перехватывать с помощью PHP try catch finally только, если это не оказывает негативного влияния на остальные функции приложения.

Например: если API-запрос к внешнему сервису выдает ошибку, то вы можете перехватить исключение и вывести дружественное пользователю сообщение « Невозможно подключиться к базе данных » или « Информация о погоде недоступна ».

Не перехваченные исключения следует обрабатывать с помощью пользовательского обработчика. Так вы сможете обрабатывать не перехваченные исключения, и выводить понятные человеку сообщения или заглушки.

Данная публикация представляет собой перевод статьи « Php Exceptions: Try & Catch » , подготовленной дружной командой проекта Интернет-технологии.ру

Содержание

Модель исключений (exceptions) в PHP похожа с используемыми в других языках программирования. Исключение можно сгенерировать (выбросить) при помощи оператора throw, и можно перехватить (поймать) оператором catch. Код генерирующий исключение, должен быть окружен блоком try, для того, чтобы можно было перехватить исключение. Каждый блок try должен иметь как минимум один соответствующий ему блок catch или finally.

Генерируемый объект должен принадлежать классу Exception или наследоваться от Exception. Попытка сгенерировать исключение другого класса приведет к фатальной ошибке PHP.

catch

Можно использовать несколько блоков catch, перехватывающих различные классы исключений. Нормальное выполнение (когда не генерируются исключения в блоках try) будет продолжено за последним блоком catch. Исключения могут быть сгенерированы (или вызваны еще раз) оператором throw внутри блока catch.

При генерации исключения код, следующий после описываемого выражения, не будет выполнен, а PHP попытается найти первый блок catch, перехватывающий исключение данного класса. Если исключение не будет перехвачено, PHP выдаст фатальную ошибку: "Uncaught Exception . " (Неперехваченное исключение), если не был определен обработчик ошибок при помощи функции set_exception_handler() .

В PHP 7.1 и выше, блок catch может принимать несколько типов исключений с помощью символа (|). Это полезно, когда разные исключения из разных иерархий классов обрабатываются одинаково.

finally

В PHP 5.5 и более поздних версиях блок finally также можно использовать после или вместо блока catch. Код в блоке finally всегда будет выполняться после кода в блоках try и catch, независимо от того, было ли выброшено исключение, перед тем как продолжится нормальное выполнение кода.

Примечания

Внутренние функции PHP в основном используют сообщения об ошибках, и только новые объектно-ориентированные расширения используют исключения. Однако, ошибки можно легко преобразовать в исключения с помощью класса ErrorException.

Читайте также:  Led подсветка что это такое

Примеры

Пример #3 Выбрасывание исключений

function inverse ( $x ) <
if (! $x ) <
throw new Exception ( ‘Деление на ноль.’ );
>
return 1 / $x ;
>

try <
echo inverse ( 5 ) . "
" ;
echo inverse ( 0 ) . "
" ;
> catch ( Exception $e ) <
echo ‘Выброшено исключение: ‘ , $e -> getMessage (), "
" ;
>

// Продолжение выполнения
echo "Привет, мир
" ;
?>

Результат выполнения данного примера:

Пример #4 Вложенные исключения

function inverse ( $x ) <
if (! $x ) <
throw new Exception ( ‘Деление на ноль.’ );
>
return 1 / $x ;
>

try <
echo inverse ( 5 ) . "
" ;
> catch ( Exception $e ) <
echo ‘Поймано исключение: ‘ , $e -> getMessage (), "
" ;
> finally <
echo "Первый блок finally.
" ;
>

try <
echo inverse ( 0 ) . "
" ;
> catch ( Exception $e ) <
echo ‘Поймано исключение: ‘ , $e -> getMessage (), "
" ;
> finally <
echo "Второй блок finally.
" ;
>

// Продолжение нормального выполнения
echo "Привет, мир
" ;
?>

Результат выполнения данного примера:

Пример #5 Вложенные исключения

class Test <
public function testing () <
try <
try <
throw new MyException ( ‘foo!’ );
> catch ( MyException $e ) <
// повторный выброс исключения
throw $e ;
>
> catch ( Exception $e ) <
var_dump ( $e -> getMessage ());
>
>
>

$foo = new Test ;
$foo -> testing ();

Результат выполнения данного примера:

Пример #6 Обработка нескольких исключений в одном блоке catch

class MyOtherException extends Exception

class Test <
public function testing () <
try <
throw new MyException ();
> catch ( MyException | MyOtherException $e ) <
var_dump ( get_class ( $e ));
>
>
>

$foo = new Test ;
$foo -> testing ();

Результат выполнения данного примера:

User Contributed Notes 32 notes

When catching an exception inside a namespace it is important that you escape to the global space:

function SomeFunction () <
try <
throw new Exception ( ‘Some Error Message’ );
> catch ( Exception $e ) <
var_dump ( $e -> getMessage ());
>
>

If a TRY has a FINALLY, a RETURN either in the TRY or a CATCH won’t terminate the script. Code in the same block after the RETURN will not be executed, and the RETURN itself will be "copied" to the bottom of the FINALLY block to be executed.

a RETURN in the FINALLY block will override value(s) returned from the TRY or a CATCH block.

An EXIT or a DIE always terminate the script after themselves.

function foo () <
$bar = 1 ;
try <
throw new Exception ( ‘I am Wu Xiancheng.’ );
>catch( Exception $e ) <
return $bar ;
$bar –; // this line will be ignored
>finally <
$bar ++;
>
>
echo foo (); // 2
?>

code 2

function foo () <
$bar = 1 ;
try <
throw new Exception ( ‘I am Wu Xiancheng.’ );
>catch( Exception $e ) <
return $bar ;
$bar –; // this line will be ignored
>finally <
$bar ++;
return $bar ;
>
>
echo foo (); //2
?>

code 3

function foo () <
$bar = 1 ;
try <
throw new Exception ( ‘I am Wu Xiancheng.’ );
>catch( Exception $e ) <
return $bar ;
$bar –; // this line will be ignored
>finally <
return 100 ;
>
>
echo foo (); //100
?>

If you intend on creating a lot of custom exceptions, you may find this code useful. I’ve created an interface and an abstract exception class that ensures that all parts of the built-in Exception class are preserved in child classes. It also properly pushes all information back to the parent constructor ensuring that nothing is lost. This allows you to quickly create new exceptions on the fly. It also overrides the default __toString method with a more thorough one.

interface IException
<
/* Protected methods inherited from Exception class */
public function getMessage (); // Exception message
public function getCode (); // User-defined Exception code
public function getFile (); // Source filename
public function getLine (); // Source line
public function getTrace (); // An array of the backtrace()
public function getTraceAsString (); // Formated string of trace

/* Overrideable methods inherited from Exception class */
public function __toString (); // formated string for display
public function __construct ( $message = null , $code = 0 );
>

Читайте также:  Wallet личные финансы 4pda

abstract class CustomException extends Exception implements IException
<
protected $message = ‘Unknown exception’ ; // Exception message
private $string ; // Unknown
protected $code = 0 ; // User-defined exception code
protected $file ; // Source filename of exception
protected $line ; // Source line of exception
private $trace ; // Unknown

public function __construct ( $message = null , $code = 0 )
<
if (! $message ) <
throw new $this ( ‘Unknown ‘ . get_class ( $this ));
>
parent :: __construct ( $message , $code );
>

public function __toString ()
<
return get_class ( $this ) . " ‘ < $this ->message > ‘ in < $this ->file > ( < $this ->line > )
"
. " < $this ->getTraceAsString ()> " ;
>
>
?>

Now you can create new exceptions in one line:

class TestException extends CustomException <>
?>

Here’s a test that shows that all information is properly preserved throughout the backtrace.

function exceptionTest ()
<
try <
throw new TestException ();
>
catch ( TestException $e ) <
echo "Caught TestException (‘ < $e ->getMessage ()> ‘)
< $e >
" ;
>
catch ( Exception $e ) <
echo "Caught Exception (‘ < $e ->getMessage ()> ‘)
< $e >
" ;
>
>

echo ” ;
?>

Here’s a sample output:

Table of Contents

PHP has an exception model similar to that of other programming languages. An exception can be thrown, and caught ("catched") within PHP. Code may be surrounded in a try block, to facilitate the catching of potential exceptions. Each try must have at least one corresponding catch or finally block.

The thrown object must be an instance of the Exception class or a subclass of Exception. Trying to throw an object that is not will result in a PHP Fatal Error.

catch

Multiple catch blocks can be used to catch different classes of exceptions. Normal execution (when no exception is thrown within the try block) will continue after that last catch block defined in sequence. Exceptions can be thrown (or re-thrown) within a catch block.

When an exception is thrown, code following the statement will not be executed, and PHP will attempt to find the first matching catch block. If an exception is not caught, a PHP Fatal Error will be issued with an "Uncaught Exception . " message, unless a handler has been defined with set_exception_handler() .

In PHP 7.1 and later, 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.

finally

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.

Notes

Internal PHP functions mainly use Error reporting, only modern Object oriented extensions use exceptions. However, errors can be simply translated to exceptions with ErrorException.

Examples

Example #3 Throwing an Exception

function inverse ( $x ) <
if (! $x ) <
throw new Exception ( ‘Division by zero.’ );
>
return 1 / $x ;
>

try <
echo inverse ( 5 ) . "
" ;
echo inverse ( 0 ) . "
" ;
> catch ( Exception $e ) <
echo ‘Caught exception: ‘ , $e -> getMessage (), "
" ;
>

// Continue execution
echo "Hello World
" ;
?>

The above example will output:

Example #4 Exception handling with a finally block

function inverse ( $x ) <
if (! $x ) <
throw new Exception ( ‘Division by zero.’ );
>
return 1 / $x ;
>

try <
echo inverse ( 5 ) . "
" ;
> catch ( Exception $e ) <
echo ‘Caught exception: ‘ , $e -> getMessage (), "
" ;
> finally <
echo "First finally.
" ;
>

try <
echo inverse ( 0 ) . "
" ;
> catch ( Exception $e ) <
echo ‘Caught exception: ‘ , $e -> getMessage (), "
" ;
> finally <
echo "Second finally.
" ;
>

// Continue execution
echo "Hello World
" ;
?>

The above example will output:

Example #5 Nested Exception

class Test <
public function testing () <
try <
try <
throw new MyException ( ‘foo!’ );
> catch ( MyException $e ) <
// rethrow it
throw $e ;
>
> catch ( Exception $e ) <
var_dump ( $e -> getMessage ());
>
>
>

Читайте также:  Xiaomi mi box root

$foo = new Test ;
$foo -> testing ();

The above example will output:

Example #6 Multi catch exception handling

class MyOtherException extends Exception

class Test <
public function testing () <
try <
throw new MyException ();
> catch ( MyException | MyOtherException $e ) <
var_dump ( get_class ( $e ));
>
>
>

$foo = new Test ;
$foo -> testing ();

The above example will output:

User Contributed Notes 32 notes

When catching an exception inside a namespace it is important that you escape to the global space:

function SomeFunction () <
try <
throw new Exception ( ‘Some Error Message’ );
> catch ( Exception $e ) <
var_dump ( $e -> getMessage ());
>
>

If a TRY has a FINALLY, a RETURN either in the TRY or a CATCH won’t terminate the script. Code in the same block after the RETURN will not be executed, and the RETURN itself will be "copied" to the bottom of the FINALLY block to be executed.

a RETURN in the FINALLY block will override value(s) returned from the TRY or a CATCH block.

An EXIT or a DIE always terminate the script after themselves.

function foo () <
$bar = 1 ;
try <
throw new Exception ( ‘I am Wu Xiancheng.’ );
>catch( Exception $e ) <
return $bar ;
$bar –; // this line will be ignored
>finally <
$bar ++;
>
>
echo foo (); // 2
?>

code 2

function foo () <
$bar = 1 ;
try <
throw new Exception ( ‘I am Wu Xiancheng.’ );
>catch( Exception $e ) <
return $bar ;
$bar –; // this line will be ignored
>finally <
$bar ++;
return $bar ;
>
>
echo foo (); //2
?>

code 3

function foo () <
$bar = 1 ;
try <
throw new Exception ( ‘I am Wu Xiancheng.’ );
>catch( Exception $e ) <
return $bar ;
$bar –; // this line will be ignored
>finally <
return 100 ;
>
>
echo foo (); //100
?>

If you intend on creating a lot of custom exceptions, you may find this code useful. I’ve created an interface and an abstract exception class that ensures that all parts of the built-in Exception class are preserved in child classes. It also properly pushes all information back to the parent constructor ensuring that nothing is lost. This allows you to quickly create new exceptions on the fly. It also overrides the default __toString method with a more thorough one.

interface IException
<
/* Protected methods inherited from Exception class */
public function getMessage (); // Exception message
public function getCode (); // User-defined Exception code
public function getFile (); // Source filename
public function getLine (); // Source line
public function getTrace (); // An array of the backtrace()
public function getTraceAsString (); // Formated string of trace

/* Overrideable methods inherited from Exception class */
public function __toString (); // formated string for display
public function __construct ( $message = null , $code = 0 );
>

abstract class CustomException extends Exception implements IException
<
protected $message = ‘Unknown exception’ ; // Exception message
private $string ; // Unknown
protected $code = 0 ; // User-defined exception code
protected $file ; // Source filename of exception
protected $line ; // Source line of exception
private $trace ; // Unknown

public function __construct ( $message = null , $code = 0 )
<
if (! $message ) <
throw new $this ( ‘Unknown ‘ . get_class ( $this ));
>
parent :: __construct ( $message , $code );
>

public function __toString ()
<
return get_class ( $this ) . " ‘ < $this ->message > ‘ in < $this ->file > ( < $this ->line > )
"
. " < $this ->getTraceAsString ()> " ;
>
>
?>

Now you can create new exceptions in one line:

class TestException extends CustomException <>
?>

Here’s a test that shows that all information is properly preserved throughout the backtrace.

function exceptionTest ()
<
try <
throw new TestException ();
>
catch ( TestException $e ) <
echo "Caught TestException (‘ < $e ->getMessage ()> ‘)
< $e >
" ;
>
catch ( Exception $e ) <
echo "Caught Exception (‘ < $e ->getMessage ()> ‘)
< $e >
" ;
>
>

echo ” ;
?>

Here’s a sample output:

Ссылка на основную публикацию
Adblock detector