В прошлой части мы разобрали маршрутизацию и увидели ключевую разницу: в Laravel роутинг — каркас приложения, а в Битриксе роутинг — стратегия (исторически “страницы+компоненты”, сейчас — D7‑роуты и контроллеры).
Теперь тема, где “каркас” встречается с реальностью проекта: база данных.
Здесь важно заранее проговорить честный нюанс сравнения:
- Laravel почти всегда воспринимает БД как вашу модель данных: вы проектируете таблицы, связи, ограничения, миграции.
- Битрикс часто воспринимает БД как часть платформы: существенный объём данных живёт в таблицах ядра (инфоблоки, пользователи, заказы, права, настройки). А ваши таблицы — это дополнение к платформе.
В этой части разберём:
- как настроить подключения и несколько соединений,
- как выглядят запросы (Query Builder / D7 Query),
- как устроены ORM (Eloquent vs D7 ORM),
- и почему миграции — это “точка боли” в Битрикс‑проектах (и как её закрывают на практике).
Подключение и конфигурация
Laravel: .env + config/database.php (и почему это удобно)
В Laravel настройки подключения обычно живут в двух местах:
.env— значения окружения (секреты и инфраструктура),config/database.php— карта соединений и опции драйверов.
Типовой минимум в .env:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=app
DB_USERNAME=app
DB_PASSWORD=secret
Практический смысл такого разделения:
- один и тот же код разворачивается в dev/stage/prod без “правок в репозитории”,
- можно держать несколько соединений (
mysql,pgsql,sqlite) и выбирать их по задаче, - можно включать “read/write splitting” (master/replica), не ломая прикладной код.
В реальных проектах сразу приучайте себя к дисциплине:
- хранить секреты в окружении,
- фиксировать настройки через
config:*кэш (на production), - избегать “магии” вида
env()из бизнес‑кода (в Laravel это плохая практика —env()предназначен для конфигов).
Битрикс: .settings.php / .settings_extra.php и соединения
В Битриксе параметры соединения обычно лежат в /bitrix/.settings.php (или дополняются в /bitrix/.settings_extra.php, а в кастомных проектах часто — и в /local/.settings*.php, если вы так договорились внутри команды).
Концептуально вы задаёте:
- тип подключения (
MysqlConnection/PgsqlConnection), - хост/пользователь/пароль/базу,
- и имя соединения (обычно
default).
Дальше в D7 вы работаете через Connection:
use Bitrix\Main\Application;
$connection = Application::getConnection(); // default
// $connection->query('SELECT 1'); // примитивный пример
Ключевая разница по “ощущению”:
- в Laravel “вы управляете БД проекта”,
- в Битриксе вы часто “подключаетесь к БД платформы”, где уже есть огромный пласт таблиц и соглашений.
Отсюда практический совет: фиксируйте соглашения команды (где живут настройки, как называются соединения, есть ли реплика/кластер, как вы переносите настройки между окружениями).
Query Builder: писать запросы без “сырого SQL”
Laravel: Query Builder (через DB::table)
Laravel Query Builder — это способ писать SQL‑логикой, оставаясь в PHP‑API:
use Illuminate\Support\Facades\DB;
$rows = DB::table('users')
->select(['id', 'name', 'email'])
->where('active', 1)
->orderByDesc('id')
->limit(10)
->get();
Где это особенно полезно:
- сложные выборки без создания “моделей”,
- отчёты и агрегаты (
groupBy,having,selectRaw), - быстрые админские экраны,
- аккуратная работа с транзакциями через
DB::transaction.
Битрикс: D7 Query (через ORM Query API)
В D7 Query чаще всего вы стартуете от *Table::query() и дальше “собираете” запрос:
use Bitrix\Main\UserTable;
$rows = UserTable::query()
->setSelect(['ID', 'NAME', 'LAST_NAME', 'EMAIL'])
->where('ACTIVE', 'Y')
->setOrder(['ID' => 'DESC'])
->setLimit(10)
->fetchAll();
Если вам ближе «объектный» стиль, можно вызвать fetchCollection() вместо fetchAll() — тогда вы получите ORM‑коллекцию Битрикса.
Illuminate\Support\Collection, и при больших объёмах данных «гидрация объектов» может быть дороже, чем fetchAll() с массивами.Сильная сторона D7‑подхода: запрос привязан к описанию сущности (таблица, поля, связи), поэтому меньше “магии строк” по проекту.
Важно не спутать: сам синтаксис запроса в D7 Query вполне сопоставим с Laravel (и особенно с Laravel Query Builder). “Вес” и “многословность” Битрикса обычно проявляются не на select/where/limit, а в двух местах:
-
Объектность результата. В Laravel
Model::query()->get()возвращаетIlluminate\Support\Collectionиз моделей (Active Record). В D7 по умолчанию вы чаще получаете массивы (fetchAll()), а если хотите объектный слой — используетеfetchObject()/fetchCollection(). Это нормально, просто другой “дефолт” и другой API коллекций (в Bitrix это ORM‑коллекции, а не Laravel Collection). -
Сложные запросы и связи. Когда вы выходите за рамки простого фильтра/сортировки и начинаете делать join’ы, вычисляемые поля, runtime‑reference и т.п., в D7 обычно появляется больше “сопутки” (карта сущностей,
Reference, runtime‑поля). В Eloquent часть этого прячется за отношениями и eager loading.
ORM: Eloquent vs Bitrix D7 ORM (и почему это разные философии)
Laravel Eloquent: Active Record “как основной путь”
Eloquent — Active Record ORM: модель одновременно и “запись”, и “логика работы с таблицей”.
Минимальный пример:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
final class Post extends Model
{
protected $fillable = ['title', 'body', 'author_id'];
}
Связи (самое важное “в реальной жизни”):
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
final class Post extends Model
{
public function author(): BelongsTo
{
return $this->belongsTo(User::class, 'author_id');
}
}
Проблема №1 у новичков — N+1 запрос. Лечится eager loading:
$posts = Post::query()
->with('author')
->latest('id')
->paginate(20);
Что делает Eloquent сильным:
- связи “из коробки” (и инструменты борьбы с N+1),
- скоупы, касты, события моделей,
- очень быстрый “time to market”.
Где нужно быть осторожным:
- Eloquent легко соблазняет “всю бизнес‑логику положить в модель”,
- сложные доменные правила лучше держать в сервисах/доменном слое, а не в Active Record.
Bitrix D7 ORM: DataManager и карта сущности
В Битриксе D7 ORM построена вокруг “табличных” классов (*Table) на базе DataManager.
Схематично (пример “как это выглядит” на уровне идеи):
use Bitrix\Main\ORM\Data\DataManager;
use Bitrix\Main\ORM\Fields\IntegerField;
use Bitrix\Main\ORM\Fields\StringField;
final class PostTable extends DataManager
{
public static function getTableName(): string
{
return 'b_my_post';
}
public static function getMap(): array
{
return [
(new IntegerField('ID'))->configurePrimary(true)->configureAutocomplete(true),
(new StringField('TITLE'))->configureRequired(true),
];
}
}
Дальше вы работаете не с “объектом‑записью” (как в Eloquent), а с таблицей/сущностью:
$result = PostTable::add([
'TITLE' => 'Привет, D7 ORM',
]);
$id = $result->getId();
Философски это ближе к Data Mapper: сущность описывается отдельно, а операции выполняются через менеджер.
Сильные стороны в контексте Битрикса:
- хорошо “ложится” на модульную архитектуру (таблицы модуля),
- явная карта полей и валидация,
- единый стиль запросов (
query()/getList()), который встречается и в ядре.
Ограничения и реальность:
- огромное количество данных в Битриксе живёт не в ваших таблицах, а в “платформенных” сущностях (инфоблоки, корзина/заказы, права),
- исторически в проектах часто смешиваются: старое API (
CIBlockElement,$DB) + D7 + прямой SQL. Это нормально для legacy, но для нового кода лучше выбирать D7 как стандарт.
Миграции и версионирование схемы
Laravel: migrations — стандарт де‑факто
В Laravel миграции — это “истина о схеме БД в репозитории”. Типовой цикл:
php artisan make:migration ...php artisan migrate- (для разработки)
php artisan migrate:fresh --seed
Пример миграции:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('body')->nullable();
$table->foreignId('author_id')->constrained('users');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('posts');
}
};
Это одновременно:
- документация схемы,
- способ доставки изменений,
- база для тестов/сидов/фабрик.
Битрикс: “из коробки” нет единого стандарта миграций (и поэтому важно договориться)
В ядре Битрикса нет универсального механизма миграций уровня Laravel, который “вшит в процесс разработки” во всех проектах.
На практике встречаются подходы:
- миграции через сторонние инструменты (самый популярный путь в продакшене),
- SQL/скрипты деплоя (ручная дисциплина),
- установка/обновление модуля как “точка применения” изменений (частично решает задачу, но хуже подходит для частых итераций).
Из реально распространённых инструментов в Битрикс‑мире:
sprint.migration(часто используют в проектах с инфоблоками и платформенными сущностями),arrilot/bitrix-migrations(подход ближе к “миграциям как коду”, но устарел и не обновляется).
Транзакции и консистентность данных
Laravel: DB::transaction()
use Illuminate\Support\Facades\DB;
DB::transaction(function () use ($data) {
// несколько записей, которые должны “либо все, либо ни одной”
});
Битрикс: транзакции через Connection
use Bitrix\Main\Application;
$connection = Application::getConnection();
$connection->startTransaction();
try {
// операции add/update/delete
$connection->commitTransaction();
} catch (\Throwable $e) {
$connection->rollbackTransaction();
throw $e;
}
Практический смысл одинаковый: если вы меняете несколько сущностей (например, заказ + позиции + остатки), транзакции — это не “оптимизация”, а базовая защита от поломанного состояния.
“Где умирает производительность”: N+1, джойны и кэш
Laravel: N+1 обычно лечится with()
Если видите цикл по моделям и внутри — обращение к связи ($post->author->name), почти всегда нужно:
- добавить
with('author'), - проверить количество запросов,
- при необходимости —
withCount,selectи индексы.
Битрикс: N+1 часто появляется на стыке “платформа ↔ ваш код”
В Битриксе N+1 часто возникает, когда:
- вы получаете список элементов (инфоблок/HL/таблица),
- а потом в цикле дотягиваете свойства/связанные данные отдельными вызовами.
Лечится комбинацией:
- D7 Query с
Reference/join (когда вы работаете с таблицами), - правильной выборкой полей/свойств (когда вы работаете с инфоблоками),
- и кэшем (в Битриксе кэш — это часть “нормального пути”, особенно на витринах).
Сравнительная таблица: работа с БД
Шкала (как и в прошлых частях): от -2 до +2.
| Критерий | Laravel (баллы) | Битрикс (баллы) | Комментарий |
|---|---|---|---|
| Миграции и версионирование схемы | +2 | -1 | В Laravel это стандарт ядра и культуры. В Битриксе нужен выбранный инструмент и дисциплина команды. |
| ORM “по‑умолчанию” и удобство чтения | +2 | +1 | Eloquent очень дружелюбен. D7 ORM мощный, но тяжелее по синтаксису. |
| Работа с “платформенными данными” (каталог/заказы/права) | 0 | +2 | В Laravel это вы строите сами или через пакеты. В Битриксе — часть платформы. |
| Контроль над SQL и гибкость сложных запросов | +1 | +1 | Оба умеют и Query Builder, и “сырые” запросы при необходимости. |
| Риск деградации слоя данных в legacy | 0 | -1 | В Битриксе часто смешиваются старое API + D7 + SQL: нужна архитектурная политика “что можно/нельзя”. |
| Тестовые данные (сидеры/фабрики как стандарт) | +2 | 0 | В Laravel это часть DX. В Битриксе обычно делают кастомно. |
| Итого за статью | +7 | +2 | |
| Общий счёт (накопительный) | +37 | +16 | Счёт накапливается по мере выхода статей. |
Практика (60–120 минут): “одна и та же предметка” в двух стеках
Цель: почувствовать разницу подходов, а не написать “идеальную архитектуру”.
Задание для Laravel
- Сделайте миграции для:
authors(id, name) иposts(id, author_id, title, body, timestamps). - Опишите модели
AuthorиPost+ связи. - Заполните тестовыми данными через seed/factory (хотя бы 20 постов).
- Сделайте endpoint (или страницу), который отдаёт список постов с автором, без N+1, с пагинацией.
Задание для Битрикса
Вариант “по‑взрослому” (рекомендуется):
- Создайте модуль
vendor.moduleи заведите таблицыb_vendor_author,b_vendor_post(через выбранный миграционный инструмент). - Опишите
AuthorTableиPostTable(D7 ORM). - Сделайте выборку 20 постов с авторами через один запрос (join/Reference).
- Отдайте результат через D7‑роутинг или D7‑контроллер (JSON).
Вариант “как часто в проектах” (не привыкайте так делать... только, чтобы понимать как может встретиться на проекте):
- Описать таблицы и
*Tableвlocal/lib/, - но зафиксировать в проекте правило миграций и структуру кода, чтобы не превратить
/localв свалку.
Вывод: Laravel даёт “культуру данных из коробки”, Битрикс — “данные платформы”
Laravel сильнее там, где вы строите приложение вокруг своей модели данных: миграции, Eloquent, сиды/фабрики — это единый поток разработки.
Битрикс сильнее там, где проект опирается на платформенные сущности и коробочные модули (контент, права, магазин) — но для “инженерного” слоя данных (ваши таблицы) вам нужно выбрать и закрепить процесс миграций и правила D7.
В следующей части перейдём к тому, как данные превращаются в UI: шаблонизация и представления (Blade vs шаблоны Битрикса и компонентный подход).