Архитектура и структура проекта (где живёт код)

3 / 21
16 мин чтения
Введение
О чём говорим

В прошлой части мы поставили оба инструмента и получили первый работающий endpoint. Теперь начинается то, что на практике важнее “Hello World”: как устроен проект и где именно должен жить ваш код, чтобы через 3 месяца вы не проклинали себя (или предыдущую команду).

Сегодня разберём:

  • структуру каталогов (Laravel и Битрикс “по умолчанию”),
  • где хранить кастомный код, чтобы не превратить проект в кашу,
  • модули/пакеты как единицы расширения,
  • MVC vs компонентный подход,
  • и наконец — Service Container / Service Locator и почему это влияет на качество кода сильнее, чем выбор ORM.

Структура файлов и каталогов

Структура проекта важна не “потому что папки”, а потому что она отвечает на главный вопрос архитектуры: где у нас живут роли — роутинг, контроллеры, модели, представления, бизнес‑сервисы, конфиги.

Чтобы не писать общие слова, начнём с прикладной карты “где что лежит”, а затем разберём нюансы.

Карта “где что лежит”: Laravel ↔ Bitrix

Архитектурная роль Laravel (типовой путь) Bitrix (типовой путь / аналог)
Точка входа (front controller) public/index.php index.php в корне сайта (плюс служебные входные точки ядра)
Маршрутизация routes/web.php, routes/api.php Исторически: ЧПУ + urlrewrite.php. Современно: D7‑роуты подключаются из local/routes/*.php (см. прошлую статью).
Контроллеры HTTP app/Http/Controllers/* 1) “контроллер‑стайл” через компоненты (/local/components/.../component.php и/или /local/components/.../class.php), 2) D7‑контроллеры на базе \Bitrix\Main\Engine\Controller обычно в local/modules/<vendor>.<module>/lib/
Модели / слой данных app/Models/* (Eloquent) D7 ORM: классы *Table / сущности обычно в local/modules/<vendor>.<module>/lib/...
Представления (HTML) resources/views/*.blade.php 1) Шаблон сайта: local/templates/<site_template>/, 2) шаблоны компонентов: .../templates/, 3) views в D7‑контроллерах: local/modules/<vendor>.<module>/views/... (см. renderView())
Бизнес‑логика (сервисы) app/Services/* / app/Actions/* (любой ваш слой) Лучше всего: сервисы/домен в local/modules/<vendor>.<module>/lib/ (или минимально — в local/lib/), а не внутри компонента/шаблона
Конфиги config/*.php + .env .settings.php / .settings_extra.php (плюс настройки модулей и окружения)
Миграции database/migrations/* В ядре нет “стандарта миграций” как в Laravel: обычно сторонние решения/скрипты/свои инструменты

Laravel: структура, заточенная под MVC (и расширяемая без боли)

Laravel из коробки даёт очень понятные “центры тяжести” (официально: Directory Structure):

  • routes/ — входные точки (web/api/console). Роуты не прячутся “где‑то”, это отдельная сущность проекта.
  • app/Http/Controllers/ — контроллеры, которые принимают запрос, вызывают сервис/домен и возвращают response.
  • app/Models/ — модели Eloquent (если вы используете “laravel‑way” для данных).
  • resources/views/ — Blade‑вьюхи: layout’ы, страницы, компоненты (про компоненты поговорим глубже в части про шаблонизацию).
  • app/Providers/ — сервис‑провайдеры: место, где вы регистрируете свои сервисы/биндинги и “вшиваете” инфраструктуру в контейнер.
  • database/ — миграции/сидеры/фабрики: данные и схема БД как часть кода.

Практическая мысль: Laravel не просто “разложил папки”, он подталкивает к разделению слоёв: HTTP отдельно, домен отдельно, представление отдельно.

Битрикс: структура, заточенная под “сайт из компонентов” (и требующая договорённостей)

В Битриксе точка сборки страницы исторически другая: страница/раздел собираются компонентами внутри шаблона сайта.

Базовая структура (официально: Структура директорий):

        site-root/
  local/      # ваш код и кастомизация
  upload/     # файлы
  bitrix/     # ядро

    

Но архитектурно важнее — что находится внутри local/:

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

  • Шаблон сайта обычно живёт в local/templates/<site_template>/. Это аналог “глобального layout’а” и структуры страниц: шапка/подвал, общие стили, подключения.
  • Шаблоны компонентов могут быть:
    • рядом с компонентом в local/components/<vendor>/<name>/templates/<template>/,
    • или переопределены на уровне шаблона сайта (частая практика для кастомизации без “форка” компонента).

Компонентный подход в деталях: Структура компонента, Шаблоны компонента, Простые и комплексные компоненты.

2) “Контроллер” в классическом понимании: чаще всего это компонент

Во многих проектах роль “контроллера” фактически выполняет компонент — в формате component.php или пары class.php + templates/ (два распространённых варианта реализации):

  • получает вход (параметры, запрос),
  • собирает данные (часто — через API/ORM/сервисы),
  • отдаёт массив в шаблон компонента.

Здесь важная развилка архитектуры:

  • если в component.php/class.php живёт бизнес‑логика — проект быстро деградирует,
  • если component.php/class.php тонкий (оркестратор), а домен вынесен — проект “держит форму”.

3) “Вьюхи как во фреймворке”: D7‑контроллеры умеют рендерить представления

Если вы строите проект в более MVC‑стиле, в Битриксе можно (и это уже “официальный путь”) использовать D7‑контроллеры и возвращать HTML через renderView().

Важно: система ищет шаблон по пути вида local/modules/<vendor>.<module>/views/.... Это делает слой “представлений” в Битриксе ближе к классическому фреймворку, а не только к компонентам.

Документация: Контроллеры → Рендеринг представления (renderView).

4) Модели и бизнес‑логика: модуль как “нормальный дом”

Если вы хотите структуру уровня Laravel, самый устойчивый путь — выделять бизнес‑логику в модуль:

  • local/modules/<vendor>.<module>/lib/ — классы домена, сервисы, интеграции;
  • здесь же обычно живут D7 ORM‑классы (*Table и связанные сущности);
  • здесь же уместны D7‑контроллеры (Engine Controller), если вы строите API/роутинг “по‑фреймворковому”.

Да, “можно и в local/lib/”, но модуль даёт границы, которые особенно нужны, когда проект растёт.

Laravel: “пакет = Composer + сервис‑провайдер”

Пакет в Laravel — это обычная Composer‑зависимость, которая может:

  • добавить классы и конфиг,
  • зарегистрировать сервисы через Service Provider,
  • добавить роуты/миграции/команды/вьюхи.

Фундаментальный механизм — контейнер и провайдеры: Service Container, Service Providers.

Битрикс: “модуль = часть платформы со своим жизненным циклом”

Модуль в Битриксе — это “встроенная” единица системы: вы можете ставить/снимать модуль, он регистрируется, добавляет таблицы, события, настройки, админку, API.

Если вы хотите проект уровня “не один лендинг”, то модуль — зачастую лучший ответ на вопрос “куда класть бизнес‑код”, потому что он:

  • изолирует доменную логику от компонентов,
  • даёт структуру и границы (что особенно важно, когда в проекте 5+ разработчиков),
  • уменьшает хаос обновлений и копипаста.

MVC в Laravel: “HTTP‑слой → домен → инфраструктура”

Классическая (и самая здравая) картина в Laravel выглядит так:

  • Route: определяет входную точку,
  • Controller: тонкий слой оркестрации,
  • Service/Action: бизнес‑логика,
  • Model (Eloquent) / Repository: доступ к данным,
  • View / API Resource: представление результата.

Пример “как принято” (условно):

        // Controller: получает запрос и вызывает сервис
final class OrderController
{
    public function store(StoreOrderRequest $request, CreateOrder $action)
    {
        $order = $action->handle($request->validated());
        return response()->json(['id' => $order->id]);
    }
}

    

Ключ не в том, что “MVC красиво”, а в том, что Laravel поощряет разделение ответственности через предсказуемые точки расширения.

Компонентный подход в Битриксе: “страница собирается компонентами”

В Битриксе исторически центральная единица — компонент:

  • он получает параметры (из шаблона/настроек),
  • делает выборки/готовит данные,
  • передаёт их в шаблон компонента.

Если упрощать, “страница” часто становится композицией компонентов, а “контроллер” как явная сущность может отсутствовать.

Это не плохо и не хорошо — это просто другой центр тяжести:

  • плюс: удобно для CMS‑логики и контентных страниц, есть готовые компоненты,
  • минус: если бизнес‑логика попадает в компоненты, проект быстро превращается в “spaghetti components”.

Практический вывод: в Битриксе особенно важно сознательно выстраивать слои, потому что платформа сама по себе “не заставляет”.

Service Container (Laravel) vs Service Locator (Bitrix): почему это вообще важно

Laravel: зависимости приходят “снаружи” (DI по умолчанию)

Laravel построен вокруг контейнера зависимостей: вы описываете, как создать сервис, а затем получаете его через:

  • constructor injection,
  • method injection,
  • или через app(SomeClass::class) / фасады (но это отдельная тема).

Документация: Service Container, Facades.

Это даёт очень практичные вещи:

  • код проще тестировать (можно подменять зависимости),
  • классы имеют явные зависимости,
  • меньше скрытой магии “откуда взялся объект”.

Битрикс: Service Locator как DI‑механизм (и как он реально работает)

В Битриксе Service Locator есть официально: \Bitrix\Main\DI\ServiceLocator (PSR‑11, доступен с версии main 20.5.400). Документация: Service Locator.

На практике это означает два важных “архитектурных” эффекта:

  1. Вы можете регистрировать сервисы.settings.php ядра или в .settings.php модуля) и получать их по коду/классу — то есть у вас появляется “контейнер” и контролируемое создание объектов.
  2. D7‑контроллеры умеют автовайрить зависимости: если класс не относится к встроенным “особым” аргументам и не описан в getAutoWiredParameters, система попытается взять его из Service Locator (а если не зарегистрирован — создаст напрямую).

При этом, да, в старых/типичных проектах всё ещё встречается “глобальный контекст”:

  • глобальные объекты ($USER, $APPLICATION),
  • статические фасады‑стайл классы (\Bitrix\Main\Application, \Bitrix\Main\Context),
  • “подключи модуль и используй классы”.

Это удобно “быстро сделать”, но у этого есть цена:

  • зависимости становятся неявными,
  • тестирование усложняется,
  • растёт связность кода и платформы.
Важно Service Locator не “зло”, это инструмент. Но если вы хотите архитектуру уровня “как в Laravel”, то в Битриксе полезно сознательно:
  • выносить бизнес‑логику в сервисы/классы,
  • прокидывать зависимости явно (хотя бы через конструктор),
  • уменьшать количество прямых обращений к глобальному контексту из домена.

Сравнительная таблица: структура и архитектура

Шкала (как и в прошлой части): от -2 до +2.

Критерий Laravel (баллы) Битрикс (баллы) Комментарий
“Карта ролей” понятна сразу (роуты / контроллеры / модели / вьюхи) +2 0 В Laravel почти любой слой имеет “дом”. В Битриксе аналогичные роли есть, но они распределены между шаблоном сайта, компонентами и (желательно) модулем.
Где живёт UI (представления) +2 +2 Laravel: resources/views. Битрикс: local/templates + шаблоны компонентов + views в модулях для D7‑контроллеров (renderView).
Где живёт бизнес‑логика (и как не смешать её с UI) +2 +1 В Laravel разделение поддержано структурой. В Битриксе нужно сознательно выносить домен в сервисы/модуль, иначе логика “утечёт” в component.php и шаблоны.
Модульность и расширяемость +2 +2 Laravel: Composer‑пакеты/провайдеры. Битрикс: модули. Оба подхода рабочие, просто разные по философии.
Работа с зависимостями (DI) +2 -1 В Laravel DI — норма. В Битриксе часто встречается Service Locator‑стайл и глобальный контекст — архитектура быстрее деградирует без правил.
Итого за статью +10 +4
Общий счёт (накопительный) +20 +11 Счёт будет накапливаться по мере выхода статей.
Заключение
“Структура проекта” — это не про папки, а про границы

Laravel даёт сильные границы “из коробки”: роли (роутинг/контроллеры/вьюхи/конфиг/миграции) имеют очевидные места, а зависимости естественно живут в DI‑контейнере. Это помогает даже средним командам держать проект “в форме”.

Битрикс даёт мощную платформу и компонентный подход, но границы нужно строить самим: разделять шаблон сайта / компоненты / модуль, держать домен вне component.php, и аккуратно работать с зависимостями и глобальным контекстом.

В следующей части перейдём к теме, где эти различия проявляются особенно ярко: маршрутизация (Laravel Routes vs urlrewrite vs D7‑роутинг).

🛠 Практическая работа

Разложить проект так, чтобы не было стыдно

Задание для Laravel

Сделайте минимальную вертикаль “роут → контроллер → сервис → представление”:

  1. Создайте роут в routes/web.php.
  2. Создайте контроллер в app/Http/Controllers/ (пусть он будет тонким).
  3. Создайте сервис в app/Services/ и подключите его через DI.
  4. Создайте Blade‑вьюху в resources/views/ и верните её из контроллера.

Опорные доки: Service Container, Service Providers.

Задание для Битрикса

Сделайте минимальную вертикаль “страница → компонент → сервис → шаблон компонента” (и не забудьте, что компонент бывает в вариантах component.php и class.php):

  1. Создайте кастомный компонент в local/components/<vendor>/<name>/.
  2. Вынесите бизнес‑логику из component.php/class.php в отдельный класс:
    • минимум: local/lib/...,
    • правильнее: local/modules/<vendor>.<module>/lib/....
  3. В component.php/class.php оставьте только оркестрацию: вход → вызов сервиса → $arResult → подключение шаблона.
  4. Сделайте шаблон компонента в .../templates/.default/ и подключите компонент на тестовой странице или в шаблоне сайта.

Опорные доки: Структура директорий, материалы по компонентам: Структура компонента.

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