Php выбросить ошибку

Исключения

Содержание

  • Наследование исключений

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

Если выброшено исключение, а в текущей области видимости функции нет блока catch,
исключение будет «подниматься» по стеку вызовов к вызывающей функции, пока не найдёт подходящий блок catch.
Все блоки finally, которые встретятся на этом пути, будут выполнены.
Если стек вызовов разворачивается до глобальной области видимости, не встречая подходящего блока catch,
программа завершается с неисправимой ошибкой, если не был установлен глобальный обработчик исключений.

Выброшенный объект должен наследовать (instanceof) интерфейс Throwable.
Попытка выбросить объект, который таковым не является, приведёт к неисправимой ошибке PHP.

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

catch

Блок catch определяет, как реагировать на выброшенное исключение.
Блок catch определяет один или несколько типов исключений или ошибок, которые он может обработать,
и, по желанию, переменную, которой можно присвоить исключение
(указание переменной было обязательно до версии PHP 8.0.0).
Первый блок catch, с которым столкнётся выброшенное исключение или ошибка
и соответствует типу выброшенного объекта, обработает объект.

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

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

Начиная с версии PHP 7.1.0, в блоке catch можно указывать несколько исключений,
используя символ |. Это полезно, когда разные исключения
из разных иерархий классов обрабатываются одинаково.

Начиная с версии PHP 8.0.0, имя переменной для пойманного исключения является необязательным.
Если оно не указано, блок catch будет выполнен,
но не будет иметь доступа к выброшенному объекту.

finally

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

Одно из заметных взаимодействий происходит между блоком finally и оператором return.
Если оператор return встречается внутри блоков try или catch, блок finally
всё равно будет выполнен. Более того, оператор return выполнится, когда встретится,
но результат будет возвращён после выполнения блока finally.
Кроме того, если блок finally также содержит оператор return,
возвращается значение из блока finally.

Глобальный обработчик исключений

Если исключению разрешено распространяться на глобальную область видимости,
оно может быть перехвачено глобальным обработчиком исключений, если он установлен.
Функция set_exception_handler() может задать функцию,
которая будет вызвана вместо блока catch, если не будет вызван никакой другой блок.
Эффект по сути такой же, как если бы вся программа была обёрнута в блок trycatch
с этой функцией в качестве catch.

Примечания

Замечание:

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

Пример #1 Преобразование отчётов об ошибках в исключения

<?php
function exceptions_error_handler($severity, $message, $filename, $lineno) {
throw new
ErrorException($message, 0, $severity, $filename, $lineno);
}
set_error_handler('exceptions_error_handler');
?>

Примеры

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

<?php
function inverse($x) {
if (!
$x) {
throw new
Exception('Деление на ноль.');
}
return
1/$x;
}

try {
echo

inverse(5) . "\n";
echo
inverse(0) . "\n";
} catch (
Exception $e) {
echo
'Выброшено исключение: ', $e->getMessage(), "\n";
}
// Продолжение выполнения
echo "Привет, мир\n";
?>

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

0.2
Выброшено исключение: Деление на ноль.
Привет, мир

Пример #3 Обработка исключений с помощью блока finally

<?php
function inverse($x) {
if (!
$x) {
throw new
Exception('Деление на ноль.');
}
return
1/$x;
}

try {
echo

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

try {
echo

inverse(0) . "\n";
} catch (
Exception $e) {
echo
'Поймано исключение: ', $e->getMessage(), "\n";
} finally {
echo
"Второй блок finally.\n";
}
// Продолжение нормального выполнения
echo "Привет, мир\n";
?>

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

0.2
Первый блок finally.
Поймано исключение: Деление на ноль.
Второй блок finally.
Привет, мир

Пример #4 Взаимодействие между блоками finally и return

<?phpfunction test() {
try {
throw new
Exception('foo');
} catch (
Exception $e) {
return
'catch';
} finally {
return
'finally';
}
}

echo

test();
?>

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

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

<?phpclass MyException extends Exception { }

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

<?phpclass MyException extends Exception { }

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();?>

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

Пример #7 Пример блока catch без указания переменной

Допустимо начиная с PHP 8.0.0

<?phpclass SpecificException extends Exception {}

function

test() {
throw new
SpecificException('Ой!');
}

try {

test();
} catch (
SpecificException) {
print
"Было поймано исключение SpecificException, но нам безразлично, что у него внутри.";
}
?>

Пример #8 Throw как выражение

Допустимо начиная с PHP 8.0.0

<?phpfunction test() {
do_something_risky() or throw new Exception('Всё сломалось');
}

try {

test();
} catch (
Exception $e) {
print
$e->getMessage();
}
?>

ask at nilpo dot com

14 years ago

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.

<?php
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; // Unknownpublic 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})\n"
. "{$this->getTraceAsString()}";
}
}
?>

Now you can create new exceptions in one line:

<?php
class TestException extends CustomException {}
?>

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

<?php
function exceptionTest()
{
try {
throw new
TestException();
}
catch (
TestException $e) {
echo
"Caught TestException ('{$e->getMessage()}')\n{$e}\n";
}
catch (
Exception $e) {
echo
"Caught Exception ('{$e->getMessage()}')\n{$e}\n";
}
}

echo

'<pre>' . exceptionTest() . '</pre>';
?>

Here's a sample output:

Caught TestException ('Unknown TestException')
TestException 'Unknown TestException' in C:\xampp\htdocs\CustomException\CustomException.php(31)
#0 C:\xampp\htdocs\CustomException\ExceptionTest.php(19): CustomException->__construct()
#1 C:\xampp\htdocs\CustomException\ExceptionTest.php(43): exceptionTest()
#2 {main}

Johan

12 years ago

Custom error handling on entire pages can avoid half rendered pages for the users:

<?php
ob_start
();
try {
/*contains all page logic
and throws error if needed*/
...
} catch (
Exception $e) {
ob_end_clean();
displayErrorPage($e->getMessage());
}
?>

christof+php[AT]insypro.com

6 years ago

In case your E_WARNING type of errors aren't catchable with try/catch you can change them to another type of error like this:

<?php
set_error_handler
(function($errno, $errstr, $errfile, $errline){
if(
$errno === E_WARNING){
// make it more serious than a warning so it can be caught
trigger_error($errstr, E_ERROR);
return
true;
} else {
// fallback to default php error handler
return false;
}
});

try {

// code that might result in a E_WARNING
} catch(Exception $e){
// code to handle the E_WARNING (it's actually changed to E_ERROR at this point)
} finally {
restore_error_handler();
}
?>

Shot (Piotr Szotkowski)

14 years ago

‘Normal execution (when no exception is thrown within the try block, *or when a catch matching the thrown exception’s class is not present*) will continue after that last catch block defined in sequence.’

‘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().’

These two sentences seem a bit contradicting about what happens ‘when a catch matching the thrown exception’s class is not present’ (and the second sentence is actually correct).

Edu

10 years ago

The "finally" block can change the exception that has been throw by the catch block.

<?php
try{
try {
throw new \
Exception("Hello");
} catch(\
Exception $e) {
echo
$e->getMessage()." catch in\n";
throw
$e;
} finally {
echo
$e->getMessage()." finally \n";
throw new \
Exception("Bye");
}
} catch (\
Exception $e) {
echo
$e->getMessage()." catch out\n";
}
?>

The output is:

Hello catch in
Hello finally
Bye catch out

daviddlowe dot flimm at gmail dot com

5 years ago

Starting in PHP 7, the classes Exception and Error both implement the Throwable interface. This means, if you want to catch both Error instances and Exception instances, you should catch Throwable objects, like this:

<?phptry {
throw new
Error( "foobar" );
// or:
// throw new Exception( "foobar" );
}
catch (
Throwable $e) {
var_export( $e );
}
?>

Simo

8 years ago

#3 is not a good example. inverse("0a") would not be caught since (bool) "0a" returns true, yet 1/"0a" casts the string to integer zero and attempts to perform the calculation.

mlaopane at gmail dot com

5 years ago

<?php/**
* You can catch exceptions thrown in a deep level function
*/
function employee()
{
throw new \
Exception("I am just an employee !");
}

function

manager()
{
employee();
}

function

boss()
{
try {
manager();
} catch (\
Exception $e) {
echo
$e->getMessage();
}
}
boss(); // output: "I am just an employee !"

telefoontoestel at nospam dot org

9 years ago

When using finally keep in mind that when a exit/die statement is used in the catch block it will NOT go through the finally block.

<?php
try {
echo
"try block<br />";
throw new
Exception("test");
} catch (
Exception $ex) {
echo
"catch block<br />";
} finally {
echo
"finally block<br />";
}
// try block
// catch block
// finally block
?>

<?php
try {
echo
"try block<br />";
throw new
Exception("test");
} catch (
Exception $ex) {
echo
"catch block<br />";
exit(
1);
} finally {
echo
"finally block<br />";
}
// try block
// catch block
?>

Tom Polomsk

8 years ago

Contrary to the documentation it is possible in PHP 5.5 and higher use only try-finally blocks without any catch block.

tianyiw at vip dot qq dot com

13 days ago

Easy to understand `finally`.
<?php
try {
try {
echo
"before\n";
1 / 0;
echo
"after\n";
} finally {
echo
"finally\n";
}
} catch (\
Throwable) {
echo
"exception\n";
}
?>
# Print:
before
finally
exception

Sawsan

11 years ago

the following is an example of a re-thrown exception and the using of getPrevious function:

<?php

$name

= "Name";//check if the name contains only letters, and does not contain the word nametry
{
try
{
if (
preg_match('/[^a-z]/i', $name))
{
throw new
Exception("$name contains character other than a-z A-Z");
}
if(
strpos(strtolower($name), 'name') !== FALSE)
{
throw new
Exception("$name contains the word name");
}
echo
"The Name is valid";
}
catch(
Exception $e)
{
throw new
Exception("insert name again",0,$e);
}
}

catch (

Exception $e)
{
if (
$e->getPrevious())
{
echo
"The Previous Exception is: ".$e->getPrevious()->getMessage()."<br/>";
}
echo
"The Exception is: ".$e->getMessage()."<br/>";
}
?>

ilia-yats at ukr dot net

8 months ago

Note some undocumented details about exceptions thrown from 'finally' blocks.

When exception is thrown from 'finally' block, it overrides the original not-caught (or re-thrown) exception. So the behavior is similar to 'return': value returned from 'finally' overrides the one returned earlier. And the original exception is automatically appended to the exceptions chain, i.e. becomes 'previous' for the new one. Example:
<?php
try {
try {
throw new
Exception('thrown from try');
} finally {
throw new
Exception('thrown from finally');
}
} catch(
Exception $e) {
echo
$e->getMessage();
echo
PHP_EOL;
echo
$e->getPrevious()->getMessage();
}
// will output:
// thrown from finally
// thrown from try
?>

Example with re-throwing:
<?php
try {
try {
throw new
Exception('thrown from try');
} catch (
Exception $e) {
throw new
Exception('thrown from catch');
} finally {
throw new
Exception('thrown from finally');
}
} catch(
Exception $e) {
echo
$e->getMessage();
echo
PHP_EOL;
echo
$e->getPrevious()->getMessage();
}
// will output:
// thrown from finally
// thrown from catch
?>

The same happens even if explicitly pass null as previous exception:
<?php
try {
try {
throw new
Exception('thrown from try');
} finally {
throw new
Exception('thrown from finally', null, null);
}
} catch(
Exception $e) {
echo
$e->getMessage();
echo
PHP_EOL;
echo
$e->getPrevious()->getMessage();
}
// will output:
// thrown from finally
// thrown from try
?>

Also it is possible to pass previous exception explicitly, the 'original' one will be still appended to the chain, e.g.:
<?php
try {
try {
throw new
Exception('thrown from try');
} finally {
throw new
Exception(
'thrown from finally',
null,
new
Exception('Explicitly set previous!')
);
}
} catch(
Exception $e) {
echo
$e->getMessage();
echo
PHP_EOL;
echo
$e->getPrevious()->getMessage();
echo
PHP_EOL;
echo
$e->getPrevious()->getPrevious()->getMessage();
}
// will output:
// thrown from finally
// Explicitly set previous!
// thrown from try
?>

This seems to be true for versions 5.6-8.2.

lscorionjs at gmail dot com

8 months ago

<?phptry {
$str = 'hi';
throw new
Exception();
} catch (
Exception) {
var_dump($str);
} finally {
var_dump($str);
}
?>

Output:
string(2) "hi"
string(2) "hi"

Этот урок переехал в мой гитхаб: https://github.com/codedokode/pasta/blob/master/php/exceptions.md — ниже представлена старая версия, потому советую перейти и прочитать новую.


Если ты изучаешь ООП, ты наверняка натыкался на исключения. В мануале PHP описаны команды try/catch/throw и finally (доступна начиная с PHP 5.5), но не объясняется толком как их использовать. Чтобы разобраться с этим, надо узнать почему они вообще были придуманы.

А придуманы они были, чтобы сделать удобную обработку ошибок.

Для примера представим, что мы пишем приложение для вывода списка пользователей из файла на экран. Допустим, код выглядит как-то так:

$file = './users.csv';

// Загружаем список пользователей из файла в массив
$users = loadUsersFromFile($file); 

// Выводим
foreach ($users as $user) {
    echo "{$user['name']} набрал {$user['score']} очков\n";
}

Все ли тут верно? Нет, не все. Мы забыли сделать обработку ошибок. Файла может не существовать, к нему может не быть доступа, данные в нем могут быть в неверном формате. Хорошая программа, разумеется должна обрабатывать такие ситуации и выводить соответствующее сообщение.

Самый простой (но плохой) вариант — поместить код обработки и вывода ошибки прямо в loadUsersFromFile():

function loadUsersFromFile($file) {
    // Файла не существует — ошибка
    if (!file_exists($file)) {
        die("Ошибка: файл $file не существует\n");
    }

    ....
}

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

Что же, давай улучшим код и переделаем функцию, чтобы она возвращала массив из 2 элементов: если все ок, то элемент success содержит true, а элемент result содержит массив пользователей. Если же произошла ошибка, то в success будет находиться false, а в элементе error текст ошибки.

function loadUsersFromFile($file) {
    // Файла не существует — ошибка
    if (!file_exists($file)) {
        return [
            'success'   =>  false,
            'error'     =>  "файл $file не существует"
        ];
    }

    .... загружаем информацию о пользователях ....

    return [
        'success'   =>  true,
        'result'    =>  $users
    ];
}

Конечно, мы должны поменять и код, который вызывает функцию:

....
// Загружаем список пользователей в массив
$loadResult = loadUsersFromFile($file); 

// можно еще писать if (!$loadResult['success'])
if ($loadResult['success'] === false) {  
    // Выводим текст ошибки
    die("Не удалось вывести список пользователей из-за ошибки: {$loadResult['error']}\n");
}

$users = $loadResult['result'];
...

Теперь код гораздо лучше. Тот, кто вызывает функцию, может обрабатывать ошибки так, как ему хочется. Но за это нам пришлось заплатить усложнением кода: теперь мы должны после каждого вызова писать if и проверять, успешно ли выполнилась функция. Когда функций много, и каждая может вернуть ошибку, код начинает наполовину состоять из таких проверок.

Выбрасываем исключение

В качестве решения проблемы были придуманы исключения. Если в функции произошла какая-то ошибка и она не может выполнить свою работу, то она выбрасывает исключение командой throw:

if (!file_exists($file)) {
    throw new Exception("Ошибка: файл $file не существует");
}

Исключение — это объект встроенного в PHP класса Exception (мануал по Exception) или его наследника. Объект исключения содержит подробности о причинах ошибки. Также, в PHP есть еще другие классы исключений, которые ты можешь использовать: http://php.net/manual/ru/spl.exceptions.php

В PHP7 определение расширено: исключения не обязаны наследоваться от Exception, это может быть любой класс, реализующий интерфейс Throwable, а так как сам Exception его реализует, то его наследники по-прежнему будут работать.

Также, ты можешь написать свой класс исключений, унаследовав его от Exception. В этом случае ты даже можешь добавить туда свои методы и свойства. Свой класс надо писать, если ты хочешь позже ловить выброшенное функцией исключение или добавить какие-то дополнительные подробности об ошибке (например, имя файла из которого не удалось загрузить пользователей).

Исключение выбрасывается в случае возникновения нештатной ситуации, когда функция обнаруживает что не способна выполнить свою задачу.

Исключение по умолчанию (если оно не перехватывается) выходит из всех вызовов функций до самого верха и завершает программу, выводя сообщение об ошибке. Таким образом, если ты не перехватываешь исключения, то все равно увидишь причину ошибки (а если у тебя установлено расширение xdebug то еще и стектрейс — цепочку вызовов функций, внутри которых оно произошло). И тебе больше не надо писать if:

// Если тут произойдет исключение, оно само завершит программу
// потому у нас нет необходимости проверять результат
$users = loadUsersFromFile($file);

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

Вот простой пример:

function a() 
{
    b();
}

function b()
{
    throw new Exception("Some error happened");
}

// Функция a() вызывает b() которая выбрасывает исключение. Исключение выходит
// из функции b() наверх в функцию a(), выходит из нее и, оказавшись на верхнем 
// уровне, завершает программу
a();

// Эта строчка никогда не будет выполнена
echo "Survived\n"; 

В данном примере кода исключение мгновенно выйдет из всех вложенных вызовов функций и завершит программу. Это хорошо, так как если произошла какая-то неисправимая ошибка, выполнять программу дальше нельзя. Это называется принципом fail fast (статья на Хабре).

Ловим исключения

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

Также, исключения обычно ловят на верхнем уровне программы в веб-приложениях для того, чтобы сделать свою страницу, информирующую об ошибке (так как PHP при непойманном исключении завершает программу, и пользователь видит пустую белую страницу в браузере, что плохо). В приложениях, запускаемых в командной строке, а не в браузере, обычно это не требуется, так как они не ориентированы на «обычных» пользователей.

Перехватывать исключения в теории можно двумя способами: неструктурно и структурно. Неструктурно — это когда мы задаем обработчик исключений в начале программы:

set_exception_handler(function (Exception $exception) {
    // Функция будет вызвана при возникновении исключения        
});

Этот способ ловит неперехваченные исключения любых видов во всей программе, его можно использовать для того, чтобы сделать свою страницу ошибки (об этом подробнее написано ниже). После срабатывания обработчика программа будет завершена, предотвратить это невозможно.

Структурная обработка исключений — это когда мы ловим только исключения определенных типов в опредленном месте кода. Она реализуется с помощью try/catch:

try {
    // В try пишется код, в котором мы хотим перехватывать исключения
    $users = loadUsersFromFile(...);
    ....
} catch (LoadUsersException $e) {
    // В catch мы указываем, исключения каких классов хотим ловить.
    // В данном случае мы ловим исключения класса LoadUsersException и его 
    // наследников, то есть только те, которые выбрасывает наша функция
    // Блоков catch может быть несколько, для разных классов

    die("Ошибочка: {$e->getMessage()}\n");
}

В PHP5.5 и выше добавлен блок finally. Команды из этого блока будут выполнены после любого из блоков (try или catch) — в случае если исключения не произойдет и в случае если оно произойдет.

Перехватывать абсолютно любые типы исключений — плохая идея, так как мы обычно хотим обрабатывать только определенные, «наши», типы ошибок и не знаем что делать с другими. Чтобы перехватывать только нужные нам исключения, надо сделать свой класс на основе встроенного в PHP Exception:

class LoadUsersException extends Exception { }

Выкидывать его в throw

throw new LoadUsersException("Файл $file не существует");

И ловить в catch только наши исключения:

catch (LoadUsersException $e) {
    .... обрабатываем ошибку ...
}

Мы можем рассматривать исключения как часть интерфейса функции (часть правил работы с этой функцией). Есть аргументы, которые мы даем на вход, есть результат, который она возвращает, и есть исключения которые она может выкинуть при ошибке. И использование исключений позволяет пользователю функции (тому кто ее вызвал) решить что делать в случае ошибки.

Поддержка исключений везде

Эта система работала бы идеально, если бы стандартные функции PHP выкидывали исключения при ошибках. Но увы, по историческим причинам эти функции просто генерируют сообщение об ошибке и возвращают false. Ну например, функция чтения файла в память file_get_contents поступает именно так, и ошибка чтения файла или его отсуствие не завершает программу. Потому ты обязан ставить if после каждого вызова:

// Если файла нет, функция просто вернет false, и программа продолжит выполняться
$content = file_get_contents('file.txt');
if ($content === false) {
    ... не удалось прочесть файл ...
}

Многие разработчики забывают или ленятся проверять результат выполнения функции, и пишут некорректные программы, которые даже в случае ошибки пытаются продолжать выполнение. Это опасно, так как программа, в которой возникла ошибка, скорее всего будет дальше работать неправильно и выведет неточную информацию. Например, программа берет из базы сумму денег на счету пользователя, что-то меняет в ней и сохраняет ее обратно в базу. Если мы опечатаемся в имени переменной, может получиться так, что в базу мы запишем ноль. Хотя PHP и выведет предупреждение о несуществующей переменной, он не прерывает выполнения программы в этом случае.

Для этой проблемы есть решение. Можно установить общий обработчик ошибок (он вызывается при любой ошибке PHP, например обращении к несуществующей переменной или невозможности чтения файла), и в нем выкидывать исключение. Таким образом, любая ошибка или предупреждение приведут к выбросу исключения. Все это делается в несколько строчек с помощью встроенного в PHP класса ErrorException (мануал):

set_error_handler(function ($errno, $errstr, $errfile, $errline ) {
    // Не выбрасываем исключение если ошибка подавлена с 
    // помощью оператора @
    if (!error_reporting()) {
        return;
    }

    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
});

Этот код превращает любые ошибки и предупреждения PHP в исключения. Некоторые современные фреймворки (Slim) включают в себя такой код.

Исключения и PDO

Чтобы расширение для работы с базами данных PDO использовало исключения (например при попытке выполнить неправильно написанный SQL запрос), надо установить соответствующий параметр (рекомендуется). Без него ты будешь должен после вызова каждой функции проверять результат с помощью if:

$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Мануал: http://php.net/manual/ru/pdo.error-handling.php

Исключения и mysqli

Библиотека mysqli при ошибках не выбрасывает исключений и не генерирует предупреждений, а просто возвращает false (то есть молчит как партизан). Таким образом, после каждого действия ты должен проверять результат с помощью if, что видно в примерах кода в мануале: http://php.net/manual/ru/mysqli.query.php

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

Чтобы не писать ифы во всей программе, ты можешь сделать класс-обертку над mysqli. Или просто использовать PDO.

Так делать не надо

Не стоит ловить все исключения без разбора:

Лучше создать свой класс исключений и ловить только его.

Не надо скрывать информацию об ошибках. В 99% этот код, игнорирующий исключение, неправильный:

catch (Exception $e) {
    // ничего не делаем
}

Не надо располагать try/catch и throw на одном уровне — в этом случае проще написать if:

try {
    ... 
    throw new Exception(...);
    ...
} catch (Exception $e) {
    ...
}

Страница ошибки в веб-приложениях

По умолчанию при непойманном исключении PHP завершает скрипт. Если опция display_errors в php.ini равна 1, то PHP выводит подробности об исключении, а если она равна 0, то в браузере отображается просто белая страница. Также, PHP записывает информацию об исключении в лог ошибок сервера.

Очевидно что оба варианта не годятся для использования на продакшен («боевом») сервере: обычные пользователи не должны видеть непонятные надписи на английском о твоем приложении, и тем более не должны смотреть на пустую страницу и гадать в чем дело. А хакеры не должны видеть подробности об устройстве твоего приложения. Более того, PHP не выдает при ошибке HTTP код 500, который говорит роботам (вроде Гугла или Яндекса) что на странице ошибка и индексировать ее на надо. Разработчики PHP конечно выбрали неудачный способ поведения по умолчанию.

Потому на боевом сервере надо ставить display_errors в 0, а в приложении делать свою страницу ошибки.

Что будет, если просто не ловить исключение:

  • информация пишется в лог (ок)
  • на компьютере разработчика выводятся подробности (ок)
  • пользователь видит белую страницу или подробности ошибки (плохо)
  • отдается HTTP код 200 (плохо)

Как надо обрабатывать исключения:

  • записать информацию в лог
  • показать пользователю заглушку («сайт временно недоступен, вот контакты администратора»)
  • на заглушке выставить HTTP код ответа 503 для роботов
  • на компьютере разработчика (при display_errors = 1) можно показать подробности и стектрейс

Для реализации страницы ошибки можно либо сделать try/catch на уровне FrontController, либо установить свой обработчик исключений через set_exception_handler. Не забудь записать информацию в лог с помощью error_log($e->__toString()) — иначе ты не узнаешь об ошибках которые происходят у пользователей твоего приложения.

Если ты используешь фреймворк, возможно, в нем все это уже реализовано. Современные фрейморки, такие как Slim, Yii 2, Symfony 2, выводят заглушку при непойманном исключении. Старые — не выводят.

Ссылки

Механизм исключений существует и в других языках в таком же виде: Java, C++, Ruby, Javascript и многих других. Статья в вики:

https://ru.wikipedia.org/wiki/%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B9 (написано не очень понятно)

Также, про исключения можно почитать в книгах:

  • Мэтт Зандстра «PHP: Объекты, шаблоны, методики программирования»
  • Джордж Шлосснейгл «Профессиональное программирование на PHP»

Содержание

  • Наследование исключений

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

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

catch

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

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

finally

В PHP 5.5 и более поздних версиях также можно использовать блок finally
после или вместо блока catch. Код в блоке
finally всегда будет выполняться после кода в блоках
try и catch, вне зависимости было ли
брошено исключение или нет, перед тем как продолжится нормальное выполнение кода.
whether an exception has been thrown, and before normal execution resumes.

Примеры

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


<?php
function inverse($x) {
    if (!
$x) {
        throw new 
Exception('Деление на ноль.');
    }
    return 
1/$x;
}

try {
    echo 

inverse(5) . "\n";
    echo 
inverse(0) . "\n";
} catch (
Exception $e) {
    echo 
'Выброшено исключение: ',  $e->getMessage(), "\n";
}
// Продолжение выполнения
echo "Hello World\n";
?>

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

0.2
Выброшено исключение: Деление на ноль.
Hello World

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


<?php
function inverse($x) {
    if (!
$x) {
        throw new 
Exception('Деление на ноль.');
    }
    return 
1/$x;
}

try {
    echo 

inverse(5) . "\n";
} catch (
Exception $e) {
    echo 
'Поймано исключение: ',  $e->getMessage(), "\n";
finally {
    echo 
"Первое finally.\n";
}

try {
    echo 

inverse(0) . "\n";
} catch (
Exception $e) {
    echo 
'Поймано исключение: ',  $e->getMessage(), "\n";
finally {
    echo 
"Второе finally.\n";
}
// Продолжение нормального выполнения
echo "Hello World\n";
?>

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

0.2
Первое finally.
Поймано исключение: Деление на ноль.
Второе finally.
Hello World

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


<?phpclass MyException extends Exception { }

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();?>

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

Вернуться к: Справочник языка

Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Исключения

PHP: Введение в ООП

Отдельная большая тема в программировании – обработка ошибок. До сих пор нам удавалось избегать её, но в реальном мире, где приложения содержат тысячи, десятки и сотни тысяч (а то и все миллионы) строк кода, обработка ошибок влияет на многое: простоту модификации и расширения, адекватное поведение программы для пользователя в разных ситуациях.

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

В PHP есть функция, которая называется strpos($text, $substr). Она ищет подстроку $substr внутри текста $text и возвращает индекс начала этой подстроки в тексте. Что произойдёт, если подстрока не была найдена? Является ли это поведение ошибкой? Нет. Это штатное поведение функции. От того, что подстрока не была найдена, ничего страшного не случилось. Представьте себе любой редактор текста и механизм поиска внутри него. Ситуация, когда ничего не было найдено, возникает постоянно, и это не ломает работу программы.

Кстати, посмотрите в документацию этой функции, каким образом она говорит о том, что подстрока не была найдена?

Другая ситуация. В тех же редакторах есть функция «открыть файл». Представьте, что во время открытия файла, что-то пошло не так, например, его удалили. А это ошибка или нет? Да, в этой ситуации произошла ошибка, но это не ошибка программирования. Подобная ошибка может возникнуть всегда, независимо от желания программиста. Он не может избежать её появления. Единственное что он может, правильно реализовать её обработку.

Ещё один интересный вопрос, насколько это критичная ошибка? Должно ли оно приводить к остановке всего приложения или нет? В плохо написанных приложениях, там, где неправильно реализована обработка ошибок, такая ситуация приведёт к краху всего приложения, и оно завершится. В хорошо написанном приложении не произойдёт ничего страшного. Пользователь увидит предупреждение о том, что файл не читается, и сможет выбрать дальнейшие действия, например, попытаться прочитать его снова или выполнить другое действие.

Сказанное выше имеет очень серьёзные следствия. Одна и та же ситуация на разных уровнях может как являться ошибкой, так и быть вполне штатной ситуацией. Например, если задача функции читать файл, а она не смогла этого сделать, то с точки зрения этой функции произошла ошибка. Должна ли она приводить к остановке всего приложения? Как мы выяснили выше – не должна. О том, насколько критична данная ситуация, может решать приложение, которое использует эту функцию, но не сама функция.

Коды возврата

В языках появившихся до 1990 года (примерно), обработка ошибок выполнялась через механизм возврата функцией специального значения. Например, в Си, если функция не может выполнить свою задачу, то она должна вернуть специальное значение, либо NULL либо отрицательное число. Значение этого числа говорит о том, какая ошибка произошла. Например:

int write_log()
{
    int ret = 0; // return value 0 if success
    FILE *f = fopen("logfile.txt", "w+");

    // Проверяем, получилось ли открыть файл
    if (!f)
        return -1;

    // Проверяем, что не достигли конца файла
    if (fputs("hello logfile!", f) != EOF) {
        // continue using the file resource
    } else {
        // Файл закончился
        ret = -2;
    }

    // Не получилось закрыть файл
    if (fclose(f) == EOF)
        ret = -3;

    return ret;
}

Обратите внимание на условные конструкции и постоянное присваивание переменной ret. Фактически каждая потенциально опасная операция, должна проверяться на успешность выполнения. Если что-то пошло не так, то функция возвращает специальный код.

И вот тут начинаются проблемы. Как показывает жизнь, в большинстве ситуаций ошибка обрабатывается не там где она возникла и даже не уровнем выше. Предположим, что есть функция A, которая вызывает код, потенциально приводящий к ошибке, и она его должна уметь правильно обработать и сообщить пользователю о проблеме. При этом сама ошибка происходит внутри функции E, которая вызывается внутри A не напрямую, а через цепочку функций: A => B => C => D => E. Подумайте, к чему приводит такая схема? Все функции в этой цепочке, даже несмотря на то, что они не обрабатывают ошибку, обязаны знать про неё, отлавливать её и так же возвращать наружу код этой ошибки. В результате, количества кода, который занимается ошибками, становится так много, что за ним теряется код, выполняющий исходную задачу.

Стоит сказать, что существуют схемы обработки ошибок, которые не обладают такими недостатками, но работают по принципу возврата. Например монада Either.

Исключения

Именно на этом фоне и возник механизм исключений. Его главная цель, передать ошибку из того места, где она возникла, в место, где её можно обработать, минуя все промежуточные уровни. Другими словами, механизм исключений раскручивает стек вызовов самостоятельно.

С исключениями нужно запомнить две вещи: код, в котором произошла ошибка, выбрасывает исключение, а код, в котором ошибка обрабатывается – её ловит.

<?php

// Функция, которая может выбросить исключение
function readFile($filepath)
{
    if (!is_readable($filepath)) {
        throw new \Exception("'{$filepath}' is not readable");
    }
    // ...
}

// Где-то в другом месте программы

function run($filepath)
{
    try {
        // Функция, которая вызывает readFile. Возможно не напрямую, а через другие функции.
        // Для механизма исключений это не важно.
        openFile($filepath);
    } catch (\Exception $e) {
        // Этот блок выполняется только в одном случае, если в блоке try было выброшено исключение
        showErrorToUser($e);
    }
    // Если тут будет код, он продолжит выполняться
}

Сами исключения – это объекты класса \Exception и его наследников (о наследовании в одном из следующих курсов). Этот объект содержит внутри себя сообщение, переданное в конструктор, трассировка стека и другие полезные данные:

<?php

class Exception implements Throwable
{
    protected $message = 'Unknown exception';
    private   $string;
    protected $code = 0;
    protected $file;
    protected $line;
    private   $trace;
    private   $previous;

    public function __construct($message = '', $code = 0, Throwable $previous = null);

    final private function __clone();

    final public  function getMessage();
    final public  function getCode();
    final public  function getFile();
    final public  function getLine();
    final public  function getTrace();
    final public  function getPrevious();
    final public  function getTraceAsString();

    public function __toString();
}

Выбросить исключение проще простого, достаточно использовать инструкцию throw:

<?php

$e = new \Exception('Тут любой текст');
throw $e; // Исключение можно создать отдельно, а можно сразу же там, где используется throw

throw прерывает дальнейшее выполнение кода. В этом смысле оно подобно return, но в отличие от него, прерывает выполнение не только текущей функции, но и всего кода, вплоть до ближайшего в стеке вызовов блока catch.

Блок try/catch обычно ставится на самом верхнем уровне программы, но это не обязательно. Вполне вероятно, что есть несколько промежуточных блоков, которые могут отлавливать ошибки и снова их возбуждать. Эта тема достаточно сложная и требует некоторого опыта работы.

() translation by (you can also view the original English article)

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

Что такое исключение?

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

Здесь важно отметить, что обработка исключений отличается от обработки ошибок. При обработке ошибок мы можем использовать функцию set_error_handler для установки нашей настраиваемой функции обработки ошибок, чтобы всякий раз, когда срабатывает ошибка, она вызывала нашу функцию обработки ошибок. Таким образом, вы можете управлять ошибками. Однако, как правило, некоторые виды ошибок не восстанавливаются и прекращают выполнение программы.

С другой стороны, исключения — это что-то, что умышленно вызывает код, и ожидается, что он будет пойман в какой-то момент вашего приложения. Таким образом, мы можем сказать, что исключения восстанавливаются, а не определенные ошибки, которые не подлежат восстановлению. Если исключение, которое выбрасывается, попадает где-то в ваше приложение, выполнение программы продолжается с момента, когда исключение было поймано. А исключение, которое не попадает нигде в ваше приложение, приводит к ошибке, которое останавливает выполнение программы.

Поток управления обработкой исключений

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

Exception handling in a try catch finally blockException handling in a try catch finally blockException handling in a try catch finally block

Исключения могут быть выброшены и пойманы с помощью блоков try и catch. Вы несете ответственность за выброс исключений, если что-то произойдет, чего не ожидается. Давайте быстро рассмотрим основной поток обработки исключений, как показано в следующем псевдокоде.

1
// code before the try-catch block

2

3
try {
4
  // code

5

6
  // if something is not as expected

7
      // throw exception using the "throw" keyword

8

9
  // code, it won't be executed if the above exception is thrown

10
} catch (Exception $e) {
11
  // exception is raised and it'll be handled here

12
  // $e->getMessage() contains the error message

13
}
14

15
// code after the try-catch block, will always be executed

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

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

Выброс исключения

Исключение может быть вызвано функцией, которую вы вызываете, или вы можете использовать ключевое слово throw для выбрасывания исключения вручную. Например, вы можете проверить некоторый ввод перед выполнением любой операции и выбросить исключение, если данные недействительны.

Здесь важно отметить, что если вы выбросите исключение, но вы не определили блок catch, который должен обрабатывать это исключение, это приведет к фатальной ошибке. Поэтому вам нужно убедиться, что вы всегда определяете блок catch, если вы бросаете исключения в своем приложении.

Когда исключение попадает в блок catch, объект Exception содержит сообщение об ошибке, которое было выбрано с использованием ключевого слова throw. Переменная $e в приведенном выше примере является экземпляром класса Exception, поэтому она имеет доступ ко всем методам этого класса. В этом блоке вы должны определить свою собственную логику обработки исключений — что именно вы хотите сделать с ошибкой, которую вы поймаете.

В следующем разделе мы рассмотрим пример из реального мира, чтобы понять, как работает обработка исключений.

Пример из реального мира

В этом разделе мы построим реальный пример для демонстрации обработки исключений в PHP.

Предположим, что вы создали приложение, которое загружает конфигурацию приложения из файла config.php. Теперь важно, чтобы файл config.php присутствовал, когда ваше приложение загружается. Таким образом, ваше приложение не может работать, если файл config.php отсутствует. Так что это идеальный случай, чтобы выбросить исключение и сообщить пользователю, что им необходимо исправить проблему.

1
<?php
2
try {
3
    // init bootstrapping phase

4

5
    $config_file_path = "config.php";
6

7
    if (!file_exists($config_file_path))
8
    {
9
      throw new Exception("Configuration file not found.");
10
    }
11
 
12
    // continue execution of the bootstrapping phase

13
} catch (Exception $e) {
14
    echo $e->getMessage();
15
    die();
16
}
17
?>

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

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

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

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

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

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

Перейдем к предыдущему примеру, как показано в следующем фрагменте.

1
<?php
2
class ConfigFileNotFoundException extends Exception {}
3

4
try {
5
    // init bootstrapping phase

6

7
    $config_file_path = "config.php";
8

9
    if (!file_exists($config_file_path))
10
    {
11
      throw new ConfigFileNotFoundException("Configuration file not found.");
12
    }
13
 
14
    // continue execution of the bootstrapping phase

15
} catch (ConfigFileNotFoundException $e) {
16
    echo "ConfigFileNotFoundException: ".$e->getMessage();
17
    // other additional actions that you want to carry out for this exception

18
    die();
19
} catch (Exception $e) {
20
    echo $e->getMessage();
21
    die();
22
}
23
?>

Во-первых, мы определили класс ConfigFileNotFoundException, который расширяет основной класс Exception. Теперь он становится нашим настраиваемым классом исключений, и мы можем использовать его, когда хотим выбросить исключение ConfigFileNotFoundException в нашем приложении.

Затем мы использовали ключевое слово throw для исключения исключений ConfigFileNotFoundException в случае, если файл config.php не существует. Однако важное различие находится в блоке catch. Как вы можете видеть, мы определили два блока catch, и каждый блок используется для обнаружения различного типа исключения.

Первый получает исключения типа ConfigFileNotFoundException. Итак, если генерируемое исключение относится к типу ConfigFileNotFoundException, этот блок будет выполнен. Если тип исключения не соответствует какому-либо конкретному блоку catch, он будет соответствовать последнему, который должен поймать все генерические сообщения об исключениях.

Блок Finally

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

Попробуем понять это, используя следующий пример.

1
try {
2
  // code

3

4
  // if something is not as expected

5
      // throw exception using the "throw" keyword

6

7
  // code, it won't be executed if the above exception is thrown

8
} catch (Exception $e) {
9
  // exception is raised and it'll be handled here

10
  // $e->getMessage() contains the error message

11
} finally {
12
  // code, it'll always be executed

13
}

Код в приведенном выше примере почти то же самое с единственным исключением, что мы добавили блок finally после блока catch. И, как мы обсуждали, код в этом блоке всегда будет выполняться.

Типичные прецеденты, которые мы могли бы придумать для использования блока finally, обычно связаны с очисткой ресурсов. Например, если вы открыли соединение с базой данных или файл на диске в блоке try, вы можете выполнять задачи очистки, такие как закрытие соединения в блоке finally, так как это гарантировано.

Обработка исключений — это ключевой навык кодирования, и вы должны подумать над тем, как будут обрабатываться исключения при разработке ваших приложений. Это поможет вам обнаружить и восстановить непредвиденные ошибки в вашем приложении. Надеюсь, что этот пост вдохновит вас написать лучший код обработки ошибок!

Заключение

Сегодня мы обсудили тему обработки исключений в PHP. В первой половине статьи мы обсудили основы исключений в PHP и создали реальный пример, чтобы продемонстрировать, как они работают. В конце мы рассмотрели, как вы можете создавать пользовательские исключения, расширяя основной класс Exception.

Понравилась статья? Поделить с друзьями:

Интересное по теме:

  • Php возвращает сообщение об ошибке
  • Php вернуть ошибку 403
  • Php ziparchive ошибка
  • Php возврат ошибки 404
  • Php sqlite3 обработка ошибок

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

    ;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: