mb4it/bitrix-migration

Laravel-style versioned migrations for 1C-Bitrix (MB\Bitrix\Database\Migrations). Ships its console commands on top of mb4it/bitrix-console.

Maintainers

Package info

github.com/Dictator90/mb-bitrix-migration

pkg:composer/mb4it/bitrix-migration

Transparency log

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

0.1.1 2026-07-08 14:50 UTC

This package is auto-updated.

Last update: 2026-07-26 15:13:11 UTC


README

Версионируемые миграции для 1С-Битрикс в стиле Laravel: класс миграции с up()/down(), таблица-леджер применённых версий, батчи, откат, статус. Плюс fluent-билдеры и экспортёры сущностей Битрикса (инфоблоки, HL-блоки, агенты, почта, опции, пользователи/группы, sitemap) для генерации миграций из живой БД. Namespace — MB\Bitrix\Database\Migrations\.

Самодостаточный пакет: зависит от ядра 1С-Битрикс и от mb4it/bitrix-console (движок + свои console-команды), но НЕ от mb4it/bitrix-support. Леджер MigrationVersionTable extends \Bitrix\Main\ORM\Data\DataManager; DI-обвязка (биндинги Migrator и пр.) и CLI-команды регистрируются через провайдер пакета, который консоль подхватывает автоматически (discovery по extra.mb-console.providers).

Требования

  • PHP ^8.2
  • 1С-Битрикс (модуль main; отдельные экспортёры грузят iblock/highloadblock/seo)
  • Для запуска из консоли — mb4it/bitrix-console (команды migrate*, make:migration*)

Установка

Пакет — path-репозиторий в composer.json потребителя (модуля/проекта):

{
  "require": { 
    "mb4it/bitrix-migration": "@dev"
  }
}
composer update mb4it/bitrix-migration

Подключение — автоматическое: пакет объявляет свой console-провайдер в composer.json → extra.mb-console.providers, а mb4it/bitrix-console подхватывает его через Console\PackageManifest (читает vendor/composer/installed.json). Никакой ручной регистрации не нужно. mb4it/bitrix-support не требуется.

Быстрый старт

Сам движок — библиотека; CLI-команды даёт mb4it/bitrix-console. Обычно ставят консоль (миграции придут транзитивно) — и всё работает сразу, без настройки:

composer require mb4it/bitrix-console

Появится самодостаточный бинарь vendor/bin/bx (далее — просто bx):

bx make:migration create_orders_table   # создать файл в local/migrations
# отредактируйте up()/down() в созданном файле, затем:
bx migrate                               # применить (создаст леджер при первом запуске)
bx migrate:status                        # ran / pending / batch
bx migrate:rollback --force              # откатить последний батч

Нужно только программное использование, без CLI? Ставьте один движок:

composer require mb4it/bitrix-migration

и вызывайте app(\MB\Bitrix\Database\Migrations\Migrator::class) (см. «Программное использование»).

Что внутри

Класс Назначение
Migration Базовый абстрактный класс миграции: up() / down(), connection(), statement().
Migrator Движок: применение pending, откат батчей, fresh, статус. Поддерживает scope; ставит контекст миграции (имя + каталог) вокруг up()/down().
MigrationCreator Генератор timestamped-файла миграции из стаба (make:migration).
PathRegistry Реестр каталогов с миграциями (по умолчанию local/migrations).
Repository\{MigrationRepository, DatabaseMigrationRepository} Интерфейс + реализация леджера поверх ORM.
Entity\MigrationVersionTable DataManager, таблица mb_migration_version (леджер версий).
Entity\MigrationCreatedTable mb_migration_created — что миграция СОЗДАЛА (для не-разрушающего отката).
Entity\MigrationSnapshotTable mb_migration_snapshot — прежнее состояние обновлённых сущностей (для восстановления полей). PAYLOAD расширяется до LONGTEXT.
Support\CreationTracker Трекинг созданного + снимков; контекст текущей миграции/каталога.
Support\PortableFile Переносимые файлы: дескриптор {NAME,TYPE,DESCRIPTION} + байты (base64 CONTENT или sidecar PATH).
Support\{Blueprint, MigrationWriter, PhpPrinter, Resolver} Генерация файла миграции из экспортёра, печать PHP, переносимый резолв сущности.
Builders\*, Export\* Fluent-билдеры (apply/remove) и экспортёры живых сущностей → Blueprint.
Console\* console-команды пакета (migrate*, make:migration*) + провайдер.

Три таблицы (создаёт migrate:install, а также ленивое авто-создание):

  • mb_migration_version — леджер: ID, MIGRATION (для модуля <id>:<файл>), BATCH, APPLIED_AT.
  • mb_migration_created — сущности, созданные миграцией (чтобы откат удалял только их).
  • mb_migration_snapshot — снимок прежних значений обновлённых сущностей (чтобы откат восстанавливал поля, а не удалял сущность).

Как написать миграцию

Файл миграции — обычный PHP-файл, который возвращает анонимный экземпляр Migration. Имя файла timestamped: 2026_07_07_120000_create_orders_table.php.

<?php

declare(strict_types=1);

use MB\Bitrix\Database\Migrations\Migration;

return new class extends Migration {
    private const TABLE = 'my_orders';

    public function up(): void
    {
        $this->statement(
            'CREATE TABLE IF NOT EXISTS ' . self::TABLE . ' ('
            . 'ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY, '
            . 'TITLE VARCHAR(255) NOT NULL'
            . ')'
        );
    }

    public function down(): void
    {
        $this->statement('DROP TABLE IF EXISTS ' . self::TABLE);
    }
};

Внутри up()/down() доступны:

  • $this->connection()Bitrix\Main\DB\Connection;
  • $this->statement(string $sql) → выполнить SQL;
  • весь D7 ORM; а при установленном mb4it/bitrix-support — глобальные хелперы app(), config(), module().

down() можно оставить пустым — тогда миграция необратима (rollback просто удалит запись из леджера).

Схему таблиц ORM-сущностей (Storage\Base) удобно накатывать прямо из миграции: MyEntityTable::migrate(\Bitrix\Main\Application::getConnection()).

Где лежат файлы

  • Проектныеlocal/migrations/ (путь по умолчанию из PathRegistry).
  • Модульные<module>/migrations/ (напр. local/modules/my.module/migrations/).

Модульные миграции изолированы в леджере через scope: имя хранится как <moduleId>:<файл>, поэтому проектные и модульные миграции не смешиваются и откатываются независимо. Пустой scope — проект.

Запуск (через mb4it/bitrix-console)

bx make:migration create_orders_table            # создать файл в local/migrations
bx migrate                                        # применить pending (новый батч)
bx migrate:status                                 # статус (ran / pending / batch)
bx migrate:rollback --force                       # откатить последний батч
bx migrate:fresh --force                          # откатить всё и накатить заново

# то же для миграций модуля (scope = id модуля):
bx make:migration create_x --module my.module
bx migrate --module my.module
bx migrate:status --module my.module
bx migrate:rollback --module my.module --force

Любая команда принимает --format=json для машиночитаемого вывода (ИИ-агент).

migrate:install создаёт все три служебные таблицы (mb_migration_version, mb_migration_created, mb_migration_snapshot) — идемпотентно; они также создаются лениво при первом обращении.

Генерация миграций из живых сущностей

Экспортёры читают существующую сущность Битрикса и пишут файл миграции (up() воссоздаёт, down() откатывает). Команды и их опции — в README пакета mb4it/bitrix-console: make:migration:options, :iblock, :iblock-elements, :hlblock, :hlblock-elements, :agents, :mail, :user-groups, :users, :sitemap.

Выборочный экспорт инфоблока: --properties=CODE,… / --no-properties, --sections=ID|CODE|XML_ID,… / --no-sections, --with-elements.

Те же билдеры доступны и для ручного написания: \MB\Bitrix\Database\Migrations\Builders\OptionBuilder::make('main','x')->value('1')->apply();.

Переносимость между сайтами

Билдеры резолвят сущность по символьному ключу (CODE / XML_ID); записанный первичный ID используется лишь как фолбэк для сущностей без ключа. Поэтому миграция, перенесённая на другой сайт (где тот же ID занят несвязанной сущностью), не перезапишет чужую запись: она найдёт цель по ключу либо создаст новую.

Не-разрушающий откат и восстановление полей

down() не удаляет вслепую. Для каждой затронутой сущности:

  • создана этой миграцией → удалить;
  • существовала и лишь обновлена → восстановить прежние значения полей из снимка (mb_migration_snapshot), не удаляя сущность;
  • иначе → не трогать.

Покрыты: инфоблоки (поля + привязка к сайтам), свойства (поля + список значений enum + LINK_IBLOCK), разделы, элементы (поля + значения свойств). Вне контекста миграции (ручной вызов билдера) remove() работает как раньше — удаляет.

Перенос файлов

Картинки элементов (PREVIEW_PICTURE / DETAIL_PICTURE) и файловые свойства (тип F, одиночные и множественные) переносятся как самодостаточные файлы: MigrationWriter выносит их в sidecar-папку files/<миграция>/, а в .php остаётся ссылка PATH. При apply() файл заливается заново (новый b_file), при откате — восстанавливается из снимка. Списочные значения переносятся по enum-id; пустые — очищают свойство.

Важно: миграция теперь — это .php плюс папка files/<миграция>/. Переносите и коммитьте их вместе. Экспорт файла возможен только там, где физический файл существует; иначе файл просто пропускается.

Программное использование

Migrator разрешается из контейнера. При наличии mb4it/bitrix-support доступен глобальный хелпер app(); в standalone-режиме резолвьте через контейнер консоли или соберите объект напрямую.

use Bitrix\Main\Application as Bitrix;
use MB\Bitrix\Database\Migrations\Migrator;
use MB\Bitrix\Database\Migrations\PathRegistry;
use MB\Bitrix\Database\Migrations\Repository\DatabaseMigrationRepository;

// с mb4it/bitrix-support:
$migrator = app(Migrator::class);      // или app('migrator')

// standalone (без support) — прямая сборка:
$docRoot  = rtrim(Bitrix::getDocumentRoot(), '/\\');
$migrator = new Migrator(
    new DatabaseMigrationRepository(),
    new PathRegistry($docRoot . '/local/migrations'),
);

$applied  = $migrator->run();                       // применить pending (проект)
$reverted = $migrator->rollback(steps: 1);          // откатить последний батч
$status   = $migrator->status();                    // [{migration, ran, batch}, ...]

// для модуля — передать путь и scope:
$applied  = $migrator->run(['/abs/path/my.module/migrations'], 'my.module');

API Migrator

Метод Описание
run(?array $paths = null, string $scope = ''): array Применить все pending в scope одним батчем. Возвращает имена.
rollback(int $steps = 1, ?array $paths = null, string $scope = ''): array Откатить N последних батчей scope.
reset(?array $paths = null, string $scope = ''): array Откатить всё в scope.
status(?array $paths = null, string $scope = ''): array [{migration, ran, batch}].
getMigrationFiles(array $paths): array basename => путь, отсортировано.

Биндинги контейнера

Ключ Класс
migrator / Migrator::class Migrator (singleton)
migration.repository / MigrationRepository::class DatabaseMigrationRepository
migration.creator / MigrationCreator::class MigrationCreator (singleton)
PathRegistry::class PathRegistry (singleton, seed = local/migrations)

Кастомный путь по умолчанию

PathRegistry по умолчанию засеян local/migrations. Чтобы добавить свои каталоги (например, для авто-подхвата), переопределите singleton в своём ServiceProvider:

$this->app->singleton(PathRegistry::class, fn () => new PathRegistry(
    $docRoot . '/local/migrations',
    $docRoot . '/local/modules/my.module/migrations',
));