Разработка модуля миграций базы данных 1С-Битрикс
1С-Битрикс не имеет встроенной системы миграций в понимании Rails Migrations или Laravel Migrations. Изменения схемы базы данных накапливаются в головах разработчиков, в README-файлах или вовсе нигде — и при деплое на production что-нибудь ломается. Разработка модуля миграций решает эту проблему системно.
Почему стандартных инструментов недостаточно
Встроенный механизм обновлений Битрикс (/bitrix/modules/<module>/install/db/mysql/install.sql) рассчитан на установку модуля с нуля, а не на инкрементальные изменения. Если нужно добавить поле в таблицу, изменить тип колонки или создать индекс — это делается либо руками в phpMyAdmin, либо через скрипт, который запускается один раз вручную. Воспроизвести историю изменений на тестовом стенде становится нетривиальной задачей.
Дополнительная сложность: Битрикс активно использует как свои внутренние таблицы (b_*), так и пользовательские. Модуль миграций должен уметь работать с теми и другими, не конфликтуя с апдейтами платформы.
Архитектура модуля миграций
Модуль реализуется как полноценный модуль 1С-Битрикс в папке /bitrix/modules/vendor.migrations/. Структура:
vendor.migrations/
├── install/
│ ├── index.php # Установщик модуля
│ └── db/
│ └── mysql/
│ └── install.sql # Таблица истории миграций
├── lib/
│ ├── Migration.php # Базовый класс миграции
│ ├── Runner.php # Запуск и откат
│ └── Repository.php # Поиск файлов миграций
└── migrations/ # Директория с файлами миграций
Таблица истории хранит информацию о применённых миграциях:
CREATE TABLE `b_vendor_migrations` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`MIGRATION` varchar(255) NOT NULL,
`APPLIED_AT` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`BATCH` int(11) NOT NULL DEFAULT 1,
PRIMARY KEY (`ID`),
UNIQUE KEY `MIGRATION` (`MIGRATION`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Поле BATCH позволяет откатывать группу миграций одной командой — всё, что было применено в одном деплое.
Базовый класс и API миграции
namespace Vendor\Migrations;
use Bitrix\Main\Application;
abstract class Migration
{
protected $db;
public function __construct()
{
$this->db = Application::getConnection();
}
abstract public function up(): void;
abstract public function down(): void;
protected function addColumn(string $table, string $column, string $definition): void
{
$sql = "ALTER TABLE `{$table}` ADD COLUMN `{$column}` {$definition}";
$this->db->query($sql);
}
protected function addIndex(string $table, string $name, array $columns, bool $unique = false): void
{
$type = $unique ? 'UNIQUE INDEX' : 'INDEX';
$cols = implode('`, `', $columns);
$this->db->query("ALTER TABLE `{$table}` ADD {$type} `{$name}` (`{$cols}`)");
}
}
Конкретная миграция выглядит так:
// migrations/2024_03_15_001_add_region_to_orders.php
class Migration_2024_03_15_001_add_region_to_orders extends \Vendor\Migrations\Migration
{
public function up(): void
{
$this->addColumn('b_sale_order', 'REGION_ID', 'int(11) NULL DEFAULT NULL');
$this->addIndex('b_sale_order', 'idx_region', ['REGION_ID']);
}
public function down(): void
{
$this->db->query("ALTER TABLE `b_sale_order` DROP INDEX `idx_region`");
$this->db->query("ALTER TABLE `b_sale_order` DROP COLUMN `REGION_ID`");
}
}
Runner: применение и откат
Runner::run() сканирует папку migrations/, сравнивает с таблицей истории, применяет непримененные в хронологическом порядке. Транзакции обязательны — если миграция упала на полпути, база не должна остаться в промежуточном состоянии.
public function run(): array
{
$pending = $this->repository->getPending();
$batch = $this->getNextBatch();
$applied = [];
foreach ($pending as $migration) {
$this->db->startTransaction();
try {
$instance = new $migration();
$instance->up();
$this->markAsApplied($migration, $batch);
$this->db->commitTransaction();
$applied[] = $migration;
} catch (\Exception $e) {
$this->db->rollbackTransaction();
throw $e;
}
}
return $applied;
}
Интеграция с деплоем
Модуль подключается к CI/CD-пайплайну: после выгрузки кода на сервер выполняется автоматический запуск миграций. Для Битрикс-проектов это обычно делается через php -r "require('/var/www/bitrix/modules/main/include/prolog_before.php'); \Vendor\Migrations\Runner::getInstance()->run();" в составе деплой-скрипта.
Альтернативно — через агент Битрикс или отдельный административный раздел с кнопкой ручного запуска и журналом.
Инфоблоки и пользовательские поля
Миграции для инфоблоков — отдельный класс сложности. Добавление свойства инфоблока через SQL напрямую минует кэш Битрикса. Правильный подход — использовать ORM-методы в up():
$prop = new \CIBlockProperty();
$prop->Add([
'IBLOCK_ID' => $this->getIblockId('catalog'),
'CODE' => 'VENDOR_CODE',
'NAME' => 'Артикул поставщика',
'PROPERTY_TYPE' => 'S',
'ACTIVE' => 'Y',
]);
Типичные сроки разработки
| Конфигурация | Срок |
|---|---|
| Базовый модуль: up/down, история, CLI | 2–3 недели |
| + Административный интерфейс, журнал | +1 неделя |
| + Поддержка инфоблоков, UF-полей | +1 неделя |
| + Интеграция с CI/CD, документация | +3–5 дней |
Модуль оформляется с лицензионным соглашением, документацией по созданию миграций и примерами для разных типов изменений схемы.







