Розробка модуля міграцій бази даних 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 днів |
Модуль оформлюється з ліцензійною угодою, документацією зі створення міграцій та прикладами для різних типів змін схеми.







