Внедряем Phinx в Bitrix

Установка

Добавить пакет через composer

composer install robmorgan/phinx

Настройка

Создать в корне проекта директории

mkdir db
mkdir db/migrations
mkdir db/seeds

Создать симлинк для удобства вызова команды

ln -s vendor/bin/phinx phinx

Создать в корне проекта файл phinx.php

<?php

use Bitrix\Main\Config\Configuration;

define('NOT_CHECK_PERMISSIONS', true);
define('NO_AGENT_CHECK', true);

$_SERVER['DOCUMENT_ROOT'] = realpath(__DIR__);
include  $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php';

$connections = Configuration::getInstance()->get('connections');
$connection  = $connections['default'];

// 'authorizing' as admin
$_SESSION['SESS_AUTH']['USER_ID'] = 1;

return [
    'paths'        => [
        'migrations' => [
            '\Bitrix\Main' => '%%PHINX_CONFIG_DIR%%/db/migrations',
        ],
        'seeds' => [
            '\Bitrix\Main' => '%%PHINX_CONFIG_DIR%%/db/seeds',
        ],
    ],
    'environments' => [
        'default_migration_table' => 'phinxlog',
        'default_database'        => 'production',
        'production'             => [
            'adapter'   => 'mysql',
            'host'      => $connection['host'],
            'name'      => $connection['database'],
            'user'      => $connection['login'],
            'pass'      => $connection['password'],
            'port'      => '3306',
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
        ],
    ],
    'version_order' => 'creation',
];

Основные команды

# Создаст миграцию
php phinx create MyNewMigration

# Выполнит миграцию
php phinx migrate
php phinx migrate -f

# Откатит миграцию
php phinx rollback
php phinx rollback -t 1

# Статус миграций
php phinx status

# Создаст сид
php phinx seed:create MyNewSeeder

# Запустит сиды
php phinx seed:run
php phinx seed:run -s MyNewSeeder

Примеры миграций

Подготовим класс

use <Ваш неймспейс>
/**
 * Abstract Migration Class.
 * It is expected that the migrations you write extend from this class.
 * This abstract class proxies the various database methods to your specified
 * adapter.
 */
abstract class AbstractMigration extends \Phinx\Migration\AbstractMigration
{
    public function init(): void
    {
        define('ADMIN_SECTION', true);

        include '<Ваш путь>/bitrix/modules/main/cli/bootstrap.php';
    }
}

Создать типа инфоблока


use Bitrix\Main\Loader;
use <Ваш неймспейс>\AbstractMigration;

/**
 * Class MyNewMigration
 */
class MyNewMigration extends AbstractMigration
{
    protected const ID = 'testid';
    
    public function up(): void
    {
        Loader::includeModule('iblock');
        
        $type   = new CIBlockType();
        $result = $type->Add([
            'ID'       => self::ID,
            'SECTIONS' => 'Y',
            'LANG'     => ['ru' => ['NAME' => 'Тестовый тип инфоблока']],
        ]);
        
        if (!$result) {
            throw new RuntimeException('Failed to create iblock. Error: ' . $type->LAST_ERROR);
        }
    }
    
    public function down(): void
    {
        Loader::includeModule('iblock');
        $result = CIBlockType::Delete(self::ID);
        
        if (!$result) {
            throw new RuntimeException('Failed to remove iblock');
        }
    }
}

Создадим инфоблок

<?php

use Bitrix\Iblock\IblockTable;
use Bitrix\Main\Loader;
use <Ваш неймспейс>\AbstractMigration;

/**
 * Class CreateTestIblock
 */
class CreateTestIblock extends AbstractMigration
{
    public function up(): void
    {
        Loader::includeModule('iblock');
        
        $iblock = new CIBlock();
        $id     = $iblock->Add([
            'CODE'           => 'testiblock',
            'API_CODE'       => 'Testiblock',
            'IBLOCK_TYPE_ID' => 'testid',
            'NAME'           => 'Тестовый iblock',
            'SITE_ID'        => ['s1'],
            'GROUP_ID'       => ['1' => 'X', '2' => 'R'],
            'FIELDS'         => [
                'CODE'         => [
                    'IS_REQUIRED'   => 'Y',
                    'DEFAULT_VALUE' => [
                        'UNIQUE'          => 'N',
                        'TRANSLITERATION' => 'Y',
                        'TRANS_LEN'       => '100',
                        'TRANS_CASE'      => 'L',
                        'TRANS_SPACE'     => '-',
                        'TRANS_OTHER'     => '-',
                        'TRANS_EAT'       => 'Y',
                        'USE_GOOGLE'      => 'N',
                    ],
                ],
                'SECTION_CODE' => [
                    'IS_REQUIRED'   => 'Y',
                    'DEFAULT_VALUE' => [
                        'UNIQUE'          => 'N',
                        'TRANSLITERATION' => 'Y',
                        'TRANS_LEN'       => '100',
                        'TRANS_CASE'      => 'L',
                        'TRANS_SPACE'     => '-',
                        'TRANS_OTHER'     => '-',
                        'TRANS_EAT'       => 'Y',
                        'USE_GOOGLE'      => 'N',
                    ],
                ],
            ],
        ]);
        
        if (!$id) {
            throw new RuntimeException('Failed to create Blocks iblock. Error: ' . $iblock->LAST_ERROR);
        }
        
        (new CIBlockProperty())->Add([
            'NAME'          => 'Заголовок',
            'CODE'          => 'TITLE',
            'PROPERTY_TYPE' => 'S',
            'IBLOCK_ID'     => $id,
            'IS_REQUIRED'   => 'Y',
        ]);
        
        
        (new CIBlockProperty())->Add([
            'NAME'          => 'Изображение',
            'CODE'          => 'IMAGE',
            'PROPERTY_TYPE' => 'F',
            'IBLOCK_ID'     => $id,
        ]);
        
    }
    
    public function down(): void
    {
        Loader::includeModule('iblock');
        
        $iblock = IblockTable::query()
            ->where('API_CODE', 'Testiblock')
            ->fetchObject();
        
        if ($iblock === null) {
            return;
        }
        
        CIBlock::Delete($iblock->getId());
    }
}

Наполним инфоблок (orm D7)

<?php

use Bitrix\Main\Application;
use Bitrix\Main\Loader;
use <Ваш неймспейс>\AbstractMigration;
use Bitrix\Iblock\Elements\ElementBonuspartnerTable;

/**
 * Class FillTestiblockIblock
 */
class FillTestiblockIblock extends AbstractMigration
{ 
    public function up(): void
    {
        Loader::includeModule('iblock');
        
        self::deleteAllCurrentElements();
        
        foreach ($this->getItems() as $item) {
            
            $object = ElementTestiblockTable::createObject()
                ->setXmlId(uniqid())
                ->setName($item['name'])
                ->setSort($item['sort'])
                ->setTitle($item['name'])
                ->setImage($item['image']);
            
            $result = $object->save();
            if (!$result->isSuccess()) {
                throw new Exception(current($result->getErrorMessages()));
            }
        }
    }
    
    public function down(): void
    {
        
        self::deleteAllCurrentElements();
    }

    public static function deleteAllCurrentElements()
    {
        if (class_exists(ElementTestiblockTable::class)) {
            $elements = ElementTestiblockTable::query()
                ->addSelect('ID')
                ->fetchAll();
            
            foreach ($elements as $element) {
                CIBlockElement::Delete($element['ID']);
            }
        }
    }
    
    public function getItems()
    {
        $result = [
            [
                'sort'           => '100',
                'name'           => 'Element1',
                'image'          => $this->saveImage('/1.png'),
            ],
            [
                'sort'           => '200',
                'name'           => 'Element2',
                'image'          => $this->saveImage('/2.png'),
            ],
        ];
        
        return $result;
    }
    
    private function saveImage(string $image): ?int
    {
        $path = Application::getDocumentRoot() . '/db/source' . $image; //для картинок выделим отдульную папку
        $id   = CFile::SaveFile(array_merge(CFile::MakeFileArray($path), ['MODULE_ID' => 'iblock']), 'iblock');
        
        return $id ?: null;
    }
}

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *