Главная » Разработка Битрикс » D7 » Исключения в D7: SystemException и обработка ошибок

Исключения в D7: SystemException и обработка ошибок

Схема иерархии исключений D7 от базового SystemException в 1С-Битрикс

D7 в отличие от старого API активно использует исключения для сигнализации об ошибках — вместо возврата false или пустого значения, метод выбрасывает объект исключения с описанием проблемы. Разберём иерархию исключений D7 и как правильно их обрабатывать.

Базовая иерархия исключений D7

Exception (стандартный PHP)
└── Bitrix\Main\SystemException
    ├── Bitrix\Main\ArgumentException
    │   ├── ArgumentNullException
    │   ├── ArgumentOutOfRangeException
    │   └── ArgumentTypeException
    ├── Bitrix\Main\NotSupportedException
    ├── Bitrix\Main\ObjectNotFoundException
    └── Bitrix\Main\DB\SqlQueryException

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

Перехват конкретного типа исключения

<?php

use Bitrix\Main\ArgumentException;
use Bitrix\Main\ObjectNotFoundException;

try {
    $result = someD7Method($params);
} catch (ArgumentException $e) {
    // некорректные входные параметры — ошибка на стороне вызывающего кода
    AddMessage2Log('Invalid argument: ' . $e->getMessage(), 'my.module');
} catch (ObjectNotFoundException $e) {
    // запрошенный объект не найден — ожидаемая ситуация, не критичная ошибка
    return null;
}

Раздельная обработка разных типов исключений позволяет реагировать по-разному на разные причины сбоя — некорректный аргумент часто указывает на баг в вызывающем коде и заслуживает логирования, тогда как "объект не найден" может быть штатной, ожидаемой ситуацией, не требующей тревожного лога.

Нужна помощь с Битрикс?





    Собственные исключения проекта

    <?php
    
    namespace Vendor\Module\Exception;
    
    use Bitrix\Main\SystemException;
    
    class InsufficientStockException extends SystemException
    {
        public function __construct(int $productId, int $requested, int $available)
        {
            parent::__construct(
                "Недостаточно остатка для товара {$productId}: запрошено {$requested}, доступно {$available}"
            );
        }
    }

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

    Исключения при работе с базой данных

    <?php
    
    use Bitrix\Main\DB\SqlQueryException;
    use Bitrix\Main\Application;
    
    try {
        $connection = Application::getConnection();
        $connection->query('SELECT * FROM nonexistent_table');
    } catch (SqlQueryException $e) {
        AddMessage2Log('SQL error: ' . $e->getMessage(), 'my.module');
    }

    Ошибки SQL-запросов через D7-обёртку подключения к базе тоже выбрасываются как исключения, а не возвращаются кодом ошибки, — это отличается от старого API с глобальным $DB, где ошибки часто нужно проверять через отдельный метод после выполнения запроса.

    Смешение старого API и исключений D7

    Код, вызывающий методы старого API (возвращающие false при ошибке) внутри try/catch, рассчитанного на перехват исключений D7, не получит ожидаемого поведения — старый API не выбрасывает исключений, поэтому его ошибки нужно проверять привычным способом через возвращаемое значение, а не try/catch, даже если этот код физически расположен рядом с D7-вызовами в одном методе.

    Необработанное исключение и белый экран

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

    Частые ошибки

    • Перехватывается только общий SystemException без разбора причины. Теряется возможность по-разному реагировать на разные типы ошибок.
    • Код старого API обёрнут в try/catch как если бы он выбрасывал исключения. Реальная ошибка остаётся непойманной, поскольку старый API возвращает false, а не выбрасывает исключение.
    • Трассировка необработанного исключения видна публично на проде. Утечка чувствительной информации о структуре кода и сервера.

    Итог

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

    Нужна помощь с Битрикс?

    Исправим ошибку, доработаем сайт, ускорим Битрикс или поможем разобраться с проблемой.

    Услуги
    База знаний