К другим статьям
1С-БитриксD7АрхитектураPHP
Для разработчиков

Архитектура модуля 1С-Битрикс на D7: слои, зависимости и autoload

Модуль 1С-Битрикс часто начинается с пары обработчиков и административной страницы. Затем появляются платежи, агенты, журнал, публичные компоненты и интеграции. Если все сценарии живут в entry point-файлах и статических методах, любое изменение затрагивает несколько подсистем, а unit-тесты требуют установленного ядра.

Ниже — подход, использованный в zr.paidaccess. Он подходит не только для биллинга: те же правила полезны в интеграционных и B2B-модулях.

Слои важнее каталогов

Сначала нужно определить ответственность и разрешённые зависимости:

admin pages / components / tools
    -> application services
        -> domain services
            -> repositories / D7 ORM
            -> gateway contracts

Entry point проверяет права и запрос, вызывает сервис и формирует ответ. Он не рассчитывает тариф и не меняет несколько таблиц вручную. Доменный сервис реализует сценарий, а детали банка или другого API находятся за контрактом gateway.

Например, адаптер банка вправе проверить подпись webhook и вернуть нормализованный DTO. Но открывать доступ, активировать подписку и писать в ledger должен сервис модуля. Тогда замена банка не меняет правила доступа.

Практичная структура модуля

local/modules/vendor.module/
├── admin/                 # тонкие страницы админки
├── install/               # установка, миграции, компоненты
├── lib/
│   ├── Admin/             # orchestration административных сценариев
│   ├── Domain/            # предметные сервисы
│   ├── Gateway/           # контракты, DTO и провайдеры
│   ├── Public/            # presenters и view services
│   ├── Repository/        # работа с хранением
│   └── Tables/            # D7 DataManager
├── tests/
├── tools/                 # тонкие webhook и CLI entry points
├── autoload.production.map.php
└── include.php

Название каталогов можно изменить, но их смысл должен оставаться однозначным. DataManager описывает поля и связи таблицы, а не содержит биллинг. Admin не становится общим слоем для публичных компонентов. Utility не превращается в склад бизнес-методов.

В zr.paidaccess отдельно выделены доступ, подписка, платежи, фонд и документы. Платёжный слой зависит от контрактов gateway, но не от конкретного T-Bank-провайдера. Публичный namespace называется PublicUi, потому что public — ключевое слово PHP.

D7 ORM как инфраструктура

Класс таблицы должен описывать хранение:

final class PaymentTable extends \Bitrix\Main\ORM\Data\DataManager
{
    public static function getTableName(): string
    {
        return 'vendor_module_payment';
    }

    public static function getMap(): array
    {
        return [
            (new \Bitrix\Main\ORM\Fields\IntegerField('ID'))
                ->configurePrimary()
                ->configureAutocomplete(),
            new \Bitrix\Main\ORM\Fields\StringField('STATUS'),
        ];
    }
}

Запросы удобно скрывать за репозиторием. Это уменьшает число мест, где код зависит от особенностей D7, и позволяет тестировать доменные сервисы с in-memory реализацией.

Production autoload без сюрпризов

В Битрикс нельзя полагаться только на Composer dev-autoload: модуль должен работать после копирования на сайт. В zr.paidaccess единым источником служит autoload.production.map.php, который подключает include.php:

$classes = require __DIR__ . '/autoload.production.map.php';
\Bitrix\Main\Loader::registerAutoLoadClasses('vendor.module', $classes);

Каждый production-класс должен присутствовать в карте и указывать на существующий файл. Для расширяемых провайдеров допустим отдельный loader по строгому соглашению имён, но механизм обнаружения также нужно тестировать.

Architecture test может пройти по карте, проверить файлы и сопоставить namespace с путём. Это обнаруживает забытый класс и ошибку в регистре имени до развёртывания на Linux.

Набор правил зависимостей

  • домен не импортирует Admin, шаблоны и HTTP entry points;
  • публичный UI не зависит от административного UI;
  • общий платёжный слой не импортирует конкретный provider;
  • provider не меняет подписку, доступ и фонд напрямую;
  • в DataManager нет бизнес-сценариев;
  • установщик идемпотентен и безопасен при повторном запуске;
  • новый production-класс добавляется в autoload и сопровождается тестом.

Правила стоит хранить рядом с кодом в STRUCTURE.md и BOUNDARIES.md. Если нужен новый слой, сначала обновляется документ, затем реализация. Так в lib/ не появляются случайные каталоги с неясной ответственностью.

Порядок разработки нового сценария

  1. Описать сценарий языком предметной области.
  2. Выделить входные DTO и результат.
  3. Создать сервис без HTTP и HTML.
  4. Скрыть D7-запросы и внешние API за зависимостями.
  5. Добавить unit-тест сценария.
  6. Подключить сервис к компоненту, событию или endpoint.
  7. Обновить production map и архитектурный тест.

Практический вывод

Хорошая D7-архитектура не требует отдельного фреймворка поверх Битрикс. Достаточно направить зависимости от UI к сценариям, а от сценариев — к контрактам хранения и внешних систем. D7 ORM при этом остаётся адаптером базы, а не центром предметной модели.

Если существующий модуль уже трудно развивать, безопаснее выделять границы по одному сценарию, не переписывая всё сразу. Для аудита и такой поэтапной переработки подходит доработка проекта на 1С-Битрикс.

Нужен модуль или интеграция?

Разберём архитектуру вашей задачи на 1С-Битрикс

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