Исключения
Исключения
Модель исключений PHP напоминает модель исключений других языков программирования. PHP умеет выбрасывать — throw — и ловить — catch — исключения. Код заключают в блок try, чтобы упростить обработку вероятных исключений. Каждому блоку try указывают как минимум один блок catch или finally
Исключение будет «всплывать» по стеку вызовов функций, пока не найдёт блок catch, если функция выбросила исключение, а в текущей области видимости функции, которая её вызвала, нет блока catch. PHP выполнит каждый блок finally, который встретит по пути. Программа завершается фатальной ошибкой, когда стек вызовов не встречает блок catch и разворачивается до глобальной области видимости, если разработчик не установил глобальный обработчик исключений
В коде допустимо выбрасывать только объект исключения, тип которого при проверке оператором instanceof соответствует интерфейсу Throwable. Попытка выбросить объект, который не выполняет это условие, приведёт к фатальной ошибке PHP
Блок catch определяет, как реагировать на исключение, которое выбросил код. Блок catch определяет один или больше типов исключений или ошибок, которые он обрабатывает, и необязательную переменную, которой блок присвоит исключение
Блоки catch записывают один за другим, чтобы перехватывать исключения разных классов. Нормальное выполнение, когда блок try не выбросил исключение, продолжится после последнего блока catch, который определили в последовательности. Внутри блока catch допустимо выбрасывать, а точнее — повторно выбрасывать исключения через ключевое слово throw. PHP продолжит выполнение кода после блока catch, который сработал, если внутри блока не выбросили исключение
При появлении исключения PHP не выполнит код, который идёт за инструкцией, а попытается найти первый подходящий блок catch. PHP выдаст фатальную ошибку с сообщением Uncaught Exception ..., если исключение не поймали и через функцию set_exception_handler() не определили обработчик исключений
С PHP 8.0.0 имя переменной для исключения, которое поймал блок, необязательно. PHP выполнит блок catch, но у блока не будет доступа к объекту, который выбросил код, если переменную не указали
Блок finally также допустимо указывать после или вместо блоков catch. PHP выполнит код в блоке finally после блоков try и catch, независимо от того, выбросил ли код исключение, и до возобновления нормального выполнения
Заслуживает внимания взаимодействие между блоком finally и инструкцией return. PHP выполнит блок finally, даже если встретит внутри блоков try или catch инструкцию return. Больше того, когда PHP встречает инструкцию return, он вычисляет её, но вернёт результат после выполнения блока finally. Кроме того, PHP вернёт значение из блока finally, если блок finally тоже содержит инструкцию return
Глобальный обработчик исключений, если обработчик установили, перехватит исключение, если исключению разрешили всплывать до глобальной области видимости. Функция set_exception_handler() устанавливает функцию, которую PHP вызовет вместо блока catch, если в коде не вызвали другие блоки. Эффект по существу такой же, как если бы всю программу обернули в блок try-catch с этой функцией в качестве catch
Обработка ошибок и исключений
Настройка во время выполнения ini_set()
error_reporting - задает уровень протоколирования ошибок ( во время исполнения программы с помощью вызова error_reporting() )
display_errors - вывод ошибок на экран с остальным выводом
log_errors - определяет куда записывать сообщения об ошибках в лог сервера или в место, которое определяет директива error_log
log_errors_max_len - устанавливает длину сообщения об ошибках в байтах. Значение 0 снимает ограничение на длину сообщения
ignore_repeated_errors - отключает запись в журнал ошибок, которые повторяются. PHP считает ошибку повторной, если она возникает в том же файле и в той же строке, и если включили опцию ignore_repeated_source
report_memleaks - если настройка включена (по умолчанию), будет формироваться отчёт об утечках памяти, зафиксированных менеджером памяти Zend. На POSIX платформах этот отчёт будет направляться в поток stderr. При этом E_WARNING должна быть включена в список error_reporting
html_errors - если директиву включили, сообщения об ошибках будут включать html теги. Формат для HTML-ошибок создаёт интерактивные сообщения, которые направляют пользователя на страницу, которая описывает ошибку или функцию, которая вызвала ошибку. На такие ссылки влияют директивы docref_root и docref_ext.
error_log - имя файла, в который будут добавляться сообщения об ошибках
syslog.facility - Указывает, какой тип программы регистрирует сообщение. Действует только в том случае, если опция error_log установлена в "syslog"
Если вас не устраивает работа предустановленного обработчика ошибок, вы также можете обрабатывать множество видов ошибки с помощью своего обработчика, который можно установить вызовом функции set_error_handler(). Некоторые ошибки не могут обрабатываться пользовательским обработчиком, но те, которые могут, обрабатываются по вашему желанию: например, ваш скрипт может выдавать пользователю любую отдельную страницу ошибки, а подробную информацию записывать в лог или отсылать по почте
// Сообщать о каждой PHP-ошибке
error_reporting(E_ALL);
// То же, что и error_reporting(E_ALL);
ini_set('error_reporting', E_ALL);
#Простой пример обработки исключения
function func($x)
{
if (!$x)
{
throw new Exception('Деление на ноль');
}
return 1 / $x;
}
try {
echo func(5) . "<br>"; # 0.2 Конец
#echo func(0) . "<br>"; # php перехватил исключение: Деление на ноль Конец
} catch ( Exception $e ) {
echo "php перехватил исключение: ", $e->getMessage(), "<br>";
}
echo "Конец";
#Простой пример обработки исключения
function func($x)
{
if ($x < 0)
{
throw new Exception('Число меньше нуля');
return 1;
}
else
{
echo "Все хорошо";
}
}
try {
#echo func(5) . "<br>"; # Все хорошо Конец
echo func(-1) . "<br>"; # php перехватил исключение: Число меньше нуля Конец
} catch ( Exception $e ) {
echo "php перехватил исключение: ", $e->getMessage(), "<br>";
}
echo "Конец";
#Взаимодействие между блоками finally и return
function test() {
try {
throw new Exception('foo');
} catch (Exception $e) {
return 'catch';
} finally {
return 'finally';
}
}
echo test();