Дата последнего изменения: 19.08.2021
В D7 используется механизм исключений (exceptions).
Примеры
Если пользователь отправил форму с пустым полем Имя, то это - не исключительная ситуация. Это обычная ожидаемая ситуация, которая должна быть обработана соответствующим образом.
Если же при вызове метода API для изменения элемента инфоблока был указан пустой id элемента, то это исключительная ситуация. Она не ожидаема и продолжать изменение элемента не имеет смысла.
Если метод ожидает id пользователя, а вы передаёте строку, то это - исключение, так как метод не знает что делать со строкой в данном случае.
Если метод GetList принимает фильтр timestamp, а разработчик написал tymestamp, то это будет исключением.
Все исключения D7 наследуются от встроенного в PHP класса \Exception, который присутствует в PHP начиная с версии 5.1. У данного класса есть не переопределяемые методы getMessage(), getCode(), getFile(), getLine(), getTrace(), getTraceAsString(), а так же переопределяемый метод __toString().
Есть понятие иерархии исключений. Оно нужно для того, чтобы можно было их (исключения) обработать, посмотреть какое из них сработало и в зависимости от этого предпринять какие-то действия. Общая схема иерархии имеет вид:
\Exception
Bitrix\Main\SystemException
базовый класс всех системных исключений, от которого наследуются все остальные исключения. Данный класс переопределяет конструктор системного класса \Exception
. Если системный класс на вход принимает сообщение и код ошибки:
<?php public function __construct($message = null, $code = 0, Exception $previous = null);
, то конструктор Main\SystemException
на вход принимает кроме этого файл в котором было выброшено исключение и номер строки:
<?php public function __construct($message = "", $code = 0, $file = "", $line = 0, \Exception $previous = null);
Выбрасываемое исключение должно иметь максимально подходящий тип.
Если ваш метод создает исключение, то необходимо описать это в phpDoc метода.
В Bitrix Framework это делается таким образом:
/** * Searches connection parameters (type, host, db, login and password) by connection name * * @param string $name Connection name * @return array|null * @throws \Bitrix\Main\ArgumentTypeException * @throws \Bitrix\Main\ArgumentNullException */ protected function getConnectionParameters($name) {}
Иногда необходимо чтобы произошедшая ошибка не приводила к прерыванию выполнения скрипта. Пример такой реализации можно рассмотреть в самом продукте в виде работы административной страницы модуля CDN.
Если включён CDN, то вверху страницы отображается информация о расходе трафика. В коде это реализовано так:
$cdn_config = CBitrixCloudCDNConfig::getInstance()->loadFromOptions(); $APPLICATION->SetTitle(GetMessage("BCL_TITLE")); require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_after.php"); if (is_object($message)) echo $message->Show(); if (CBitrixCloudCDN::IsActive()) { try { if ($cdn_config->getQuota()->isExpired()) $cdn_config->updateQuota(); $cdn_quota = $cdn_config->getQuota(); if ($cdn_quota->getAllowedSize() > 0.0 || $cdn_quota->getTrafficSize() > 0.0) { CAdminMessage::ShowMessage(array( "TYPE" => "PROGRESS", "DETAILS" => ''.GetMessage("BCL_CDN_USAGE", array( "#TRAFFIC#" => CFile::FormatSize($cdn_quota->getTrafficSize()), "#ALLOWED#" => CFile::FormatSize($cdn_quota->getAllowedSize()), )).'
#PROGRESS_BAR#', "HTML" => true, "PROGRESS_TOTAL" => $cdn_quota->getAllowedSize(), "PROGRESS_VALUE" => $cdn_quota->getTrafficSize(), )); } } catch (Exception $e) { CAdminMessage::ShowMessage($e->getMessage()); } }
По коду видно, что если CDN активен, то формируется прогресс-бар с выводом информации о расходе трафика. Но если в ходе выполнения этого кода произойдёт ошибка, то будет выброшено исключение. Это исключение будет перехвачено так как весь код находится в try
и сработает ветка, после catch
, где выводится сообщение об ошибке штатной функцией. Выполнение скрипта при этом не будет прервано: