Наш блог
Показать рубрики

Миграции базы данных в 1С-Битрикс проектах с использованием Phinx

Назад к списку статей
Миграции базы данных в 1С-Битрикс проектах с использованием Phinx
В этой статье я расскажу о том, как у нас, в E-PAGES, организована одновременная работа нескольких разработчиков на одном проекте и как мы синхронизируем изменения базы данных из тестовых рабочих копий на сервер рабочего проекта.

Проблема

Допустим, существует некоторый объем задач по живому проекту, который нужно распределить и дать в работу нескольким программистам. При этом мы даже не рассматриваем работу прямо на боевом сервере, так как требуются изменения структуры некоторых частей сайта, да и есть большой риск возникновения ошибок в работе проекта, что недопустимо.

Мы в нашей компании применяем такую схему (кратко): у каждого программиста есть полная локальная копия проекта включая файлы и базу данных. В своей локальной копии программист может все спокойно ломать и не бояться, что это нарушит работу живого проекта. При этом изменения файлов, естественно, версируются с помощью системы контроля версий (VCS), в ней под каждую задачу существует отдельная ветка, в которую периодически подтягиваются изменения основной ветки разработки. Таким образом идет параллельное выполнение задач и программисты ничем друг другу не мешают. Когда настает время выливать изменения по задаче на рабочий сайт - файлы сливаются с основной веткой разработки и отправляются на боевой сервер.

Такая схема хороша в задачах, которые не требуют изменений базы данных, а таких задач на практике очень мало. В большинстве случаев при переносе файлов с изменениями на боевой сервер, требуется также выполнить какие-то действия с БД, которые программист сделал у себя локально. Эта ситуация порождает несколько больших проблем:

  • Программисту необходимо как-то запоминать что он делает с базой во время решения задачи и потом повторить эти действия на боевом севере (зачастую, важно чтоб они были выполнены в том, же порядке, в котором были сделаны и на локальной копии).
  • Ручной перенос изменений не происходит быстро и во время переноса могут возникать ошибки, связанные с тем, что уже перенесенные через VCS файлы ожидают свежую структуру БД, а ее еще нет.
  • Во время ручного выполнения изменений высока вероятность допущения ошибки и это негативно повлияет на работу проекта.
  • Нет возможности быстро откатиться к предыдущей версии структуры БД при необходимости.
  • После переноса новой версии структуры БД все остальные программисты должны будут проделать те же действия с БД или развернуть у себя новый дамп, что может перезатереть их локальные изменения по задачам.

Миграции базы данных

Для решения вышеописанных проблем мы используем миграции базы данных. Миграция - в нашем случае, это PHP-код, который производит обновление базы данных до требуемой по задаче структуре, создает свойства инфоблоков, свойства заказов, задает значения настройкам, которые хранятся в БД и т.д.

Технически, миграция - это PHP-класс, в котором реализовано всего 2 метода. Первый метод хранит в себе код, который применяет миграцию, а второй метод хранит в себе код, который ее откатывает до исходного состояния.

Для написания миграций мы используем инструмент под названием Phinx. Он предоставляет удобный интерфейс командной строки и целый ряд PHP-методов для модификации компонентов базы данных, который максимально автоматизирует процесс создания миграции. Как мы его используем в 1С-Битрикс проекте и пойдет речь ниже.

Установка и настройка Phinx

Мы активно используем Composer в наших проектах, по этому мы устанавливаем Phinx с его помощью. Прописываем в файл /local/composer.json новую зависимость:

{
  "require": {
    "robmorgan/phinx": "0.5.0"
  }
}

Затем нужно в командной строке установить зависимости с помощью команды composer install. После этого в папке /local/ появится папка vendor с установленным Phinx и всеми его зависимостями. Теперь в файле init.php нужно подключить загрузочный файл Composer'a - autoload.php

<?php
//Файл /local/php_interface/init.php

//init composer autoloader
include $_SERVER['DOCUMENT_ROOT'].'/local/vendor/autoload.php';

Теперь мы готовы к дальнейшей настройке. Phinx довольно просто подружить с 1C-Битрикс, достаточно настроить один файл конфигурации и он готов к работе. Phinx имеет несколько вариантов настройки: через файл PHP, YML или JSON. Так как Phinx требует подключение к БД сайта (он держит историю миграций в своей табличке под названием phinxlog), то мы выбрали вариант с PHP файлом конфигурации, потому что это самый простой способ скормить ему данные подключения к БД из конфигурации 1C-Битрикс.

Создаем файл phinx.php в папке /local/ с таким содержимым:

<?php
//Файл /local/phinx.php

define('NOT_CHECK_PERMISSIONS', true);
define('NO_AGENT_CHECK', true);
$GLOBALS['DBType'] = 'mysql';
$_SERVER['DOCUMENT_ROOT'] = realpath(__DIR__ . '/..');
include($_SERVER['DOCUMENT_ROOT'].'/bitrix/modules/main/include/prolog_before.php');
// manual saving of DB resource
global $DB;
$app = \Bitrix\Main\Application::getInstance();
$con = $app->getConnection();
$DB->db_Conn = $con->getResource();
// 'authorizing' as admin
$_SESSION['SESS_AUTH']['USER_ID'] = 1;


$config = include realpath(__DIR__.'/../bitrix/.settings.php');

return array(
    'paths' => array(
        'migrations' => 'migrations'
    ),
    'environments' => array(
        'default_migration_table' => 'phinxlog',
        'default_database' => 'dev',
        'dev' => array(
            'adapter' => 'mysql',
            'host' => $config['connections']['value']['default']['host'],
            'name' => $config['connections']['value']['default']['database'],
            'user' => $config['connections']['value']['default']['login'],
            'pass' => $config['connections']['value']['default']['password']
        )
    )
);

Что происходит в этом файле: в нем инициируется ядро 1С-Битиркс, а также из конфигурационного файла сайта /bitrix/.settings.php извлекается массив настроек и передается в конфиг Phinx, чтоб он мог подключиться к БД сайта. Также обратите внимание, что мы задаем в ключе path папку, в которой будут храниться файлы миграций. Эта папка будет находиться по пути /local/migrations. Стоит отметить, что этот файл есть универсальным для всех сайтов на 1С-Битрикс, так как настройки в него применяются динамически из массива настроек сайта и он также есть безопасным, ведь, если его выполнить из браузера - не будет выведено никаких данных. Этот файл смело можно хранить в системе контроля версий, потому что заполучив его, никак невозможно получить доступ к БД сайта.

После проделанных шагов можно приступать к написанию файлов миграций.

Создание файлов миграций

Рассмотрим пример, когда требуется выполнить задачу, которая подозревает в себе создание в базе нового свойства заказа, с которым будет работать ваш код. Нам нужно написать миграцию, которая создаст новое свойство заказа, а также при откате его удалит.

В Phinx предусмотрен набор команд, который позволяет упростить процесс написания миграции. Первую команду, которую мы рассмотрим - это команда create, которая автоматически создает файл миграции в правильном формате. Для ее выполнения нужно в командной строке перейти в папку /local/ проекта и выполнить команду create указав в параметре краткое название миграции.

cd path_to_project_root/local
php vendor/bin/phinx create AddNewOrderProp

После команды create нужно указывать краткое название в стиле UpperCamelCase, иначе команда выдаст предупреждение. В папке /local/migrations/ будет создан файл 20160405193841_add_new_order_prop.php, название которого состоит из timestamp на момент выполнения команды и разбитое подчеркиваниями ваше короткое название миграции, которое вы указали в самой команде.

Созданный файл имеет такое содержимое:

<?php

use Phinx\Migration\AbstractMigration;

class AddNewOrderProp extends AbstractMigration
{
    public function change()
    {

    }
}

Внутри это класс, наследуемый от Phinx\Migration\AbstractMigration и в нем уже есть один публичный метод change(). К сожалению, этот метод не работает при написании миграций для 1С-Битрикс. Он предназначен для написания миграций с использованием API Phinx, если вам нужно провести предусмотренные стандартные операции с БД, например добавить таблицу, добавить поле в таблицу, добавить новых строк в таблицу. Вся прелесть метода change() в том, что если внутри него использвоать API Phinx, то нет нужды реализовывать отдельный метод по откату миграции - он сможет откатить эти действия самостоятельно.

Так как мы используем API 1С-Битрикс в миграциях, нам нужно реализовывать два метода для применения изменений и их отката отдельно. Они называются up() и down(). Соответственно первый накатывает изменения, второй откатывает их. Вот как выглядит миграция для нашей задачи создания нового свойства заказа:

<?php

use Phinx\Migration\AbstractMigration;

class AddNewOrderProp extends AbstractMigration
{
    public function up()
    {
        \Bitrix\Main\Loader::includeModule('sale');

        $arFields = array(
            'PERSON_TYPE_ID' => 1,
            'NAME' => 'Новое свойство заказа',
            'TYPE' => 'TEXT',
            'REQUIED' => 'N',
            'DEFAULT_VALUE' => '0',
            'SORT' => 100,
            'CODE' => 'NEW_ORDER_PROP',
            'USER_PROPS' => 'N',
            'IS_LOCATION' => 'N',
            'IS_LOCATION4TAX' => 'N',
            'PROPS_GROUP_ID' => 1,
            'SIZE1' => 0,
            'SIZE2' => 0,
            'DESCRIPTION' => '',
            'IS_EMAIL' => 'N',
            'IS_PROFILE_NAME' => 'N',
            'IS_PAYER' => 'N',
            'UTIL' => 'Y'
        );

        CSaleOrderProps::Add($arFields);
    }

    public function down()
    {
        \Bitrix\Main\Loader::includeModule('sale');

        $db_props = CSaleOrderProps::GetList(
            array('SORT' => 'ASC'),
            array(
                'CODE' => 'NEW_ORDER_PROP'
            ),
            false,
            false,
            array('ID')
        );

        if ($props = $db_props->Fetch())
        {
            CSaleOrderProps::Delete($props['ID']);
        }
    }
}

Метод up() добавляет новое свойство заказа, а метод down() удаляет его при откате миграции. Теперь посмотрим как применить эту миграцию.

Запуск и откат миграций

Для запуска миграций есть команда migrate. При ее выполнении Phinx смотрит свою внутреннею табличку phinxlog и получает список миграций, которые были выполнены ранее, затем идет в папку с миграциями и получает список миграций, которые нужно накатить. Для каждой новой миграции, которая еще не накатывалась, он поочередно (в порядке добавления миграций) выполняет методы up(). Таким образом в базе появляются новые изменения.

php vendor/bin/phinx migrate

Phinx by Rob Morgan - https://phinx.org. version 0.5.0

using config file ./phinx.php
using config parser php
using migration path migrations
warning no environment specified, defaulting to: dev
using adapter mysql
using database anybag

== 20160405193841 AddNewOrderProp: migrating
== 20160405193841 AddNewOrderProp: migrated 0.0016s

All Done. Took 0.0365s

Чтоб откатить миграции назад по истории их выполнения нужно использовать команду rollback. Этой команде в параметре -t нужно указать timestamp миграции, до которой нужно откатить состояние БД. Миграции откатятся до указанной миграции НЕ включительно.

php vendor/bin/phinx rollback -t 20160405193841

Все выполненные миграции можно откатить командой rollback указав в параметре -t ноль.

Заключение

Переход на миграции в полной мере решил проблемы, описанные в начале статьи. В нашей команде каждый программист работает со своей отдельной копией базы данных проекта. При необходимости внести изменения в БД проекта - пишется миграция. Остальные программисты эти миграции получают через систему контроля версий. По завершении выполнения задачи, на боевой сервер она переносится всего 3мя командами:

git pull
composer install
php vendor/bin/phinx migrate

Но у этого подхода есть один существенный минус - увеличивается время на выполнение задачи, так как вместо того, чтоб проставить одну галочку в админке - нужно писать отдельный файл миграции и устанавливать эту галочку через API 1С-Битрикс. Хотя и он перекрывается дополнительным плюсом - разработчики ЗНАЧИТЕЛЬНО повышают свои знания внутренностей системы, так как все процессы, которые происходили ранее для них, скрытно, действиями через визуальный интерфейс, теперь выполняются ими самостоятельно через код. Также можно заметить, что со временем накапливается кодовая база миграций с решением типичных задач и в следующие разы миграция пишется на основе уже сущестущей с изменением пары полей в массиве.

Ссылки

Назад к списку статей
Подпишись на наш блог:
ПОХОЖИЕ СТАТЬИ:
Установка Composer глобально

Установка Composer глобально в Windows