Простые миграции с PHPixie Migrate

от автора

image
Запуск консольного расширения несколько недель назад позволил гораздо расширить спектр задач решаемых с помощью PHPixie и её компонентов. И теперь я рад представить вам PHPixie Migrate — утилиту для миграции баз данных. Как и другие компоненты она может работать полностью самостоятельно, и в конце статьт я приведу пример того как запустить её без фреймворка.

Апгрейд существующих проектов

Если вы уже используете PHPixie то сделать апгрейд для использования миграций совсем просто.

1. Обновить конфиг соединения с БД (database.php)

PHPixie теперь поддерживает альтернативный синтаксис где вместо одной строки соединения используются дополнительные параметры, например:

Вместо старого:

return array(     'default' => array(         'connection' => 'mysql:dbname=phpixie',         'user'     => 'phpixie',         'password' => 'phpixie',         'driver'   => 'pdo'     ) ); 

теперь используется

return array(     'default' => array(         'database' => 'phpixie',         'user'     => 'phpixie',         'password' => 'phpixie',         'adapter'  => 'mysql', // one of: mysql, pgsql, sqlite         'driver'   => 'pdo'     ) ); 

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

2. Скопировать папку /assets/migrate и конфиг файл /assets/config/migrate.php со скелета в свой проект.

Вот и все.

Конфигурация

Рассмотрим конфиг /assets/config/migrate.php:

<?php  return array(     // настройки миграций     'migrations' => array(         'default' => array(                          // имя соединения с database.php             'connection' => 'default',                          // путь в котором хранятся миграции, относительно папки /assets/migrate/             'path'       => 'migrations',              // не обязательно:                          // имя таблицы в которой хранить миграции             'migrationTable' => '__migrate',              // имя поля в таблице миграций             'lastMigrationField' => 'lastMigration'         )     ),      // настройки сидирования (об этом позже)     'seeds' => array(         'default' => array(                          // имя соединения с database.php             'connection' => 'default',                          // путь в котором хранятся сиды, относительно папки /assets/migrate/             'path' => 'seeds'         )     ) ); 

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

Создание и удаление базы

Создавать и удалять базу теперь можно прямо с консоли, это делает новая команда framework:database:

framework:database ACTION [ CONFIG ]
Create or drop a database

Arguments:
ACTION Either 'create' or 'drop'
CONFIG Migration configuration name, defaults to 'default'

То есть console framework:database create проверит существует ли база, и если нет то создаст ее, а console framework:database drop удалит ее.

Миграции

Ну а теперь о самом главном. Сначала короткое вступление для тех кто ничего подобного пока не использовал.

Миграции дают возможность хранить изменения структуры базы в коде что гораздо удобнее чем перебрасываться готовыми дампами а затем вручную изменять базу на продакшене. Принцип работы прост: в базе хранится имя последней миграции и при запуске команды будут применены все миграции которые «больше» ее в порядке natsort(), то есть если у нас есть файлы 1.sql, 2.sql… 22.sql, a последняя в базе 13.sql то выполнятся все от 14 до 22, и затем в базе сохранится 22 как имя последней. Они могут быть в формате .sql или .php.

SQL миграции

Тут все просто, это просто SQL файл в котором отдельные выражения разделяются сепаратором "— statement", например:

CREATE TABLE fairies(     id int NOT NULL,     name VARCHAR(255) );  -- statement  CREATE TABLE flowers(     id int NOT NULL,     name VARCHAR(255) ); 

PHP миграции

Это просто PHP файл с возможностью выполнения запросов и даже доступа к запросам PHPixie Database:

$this->execute("CREATE TABLE fairies(     id int NOT NULL,     name VARCHAR(255) )");  $this->message("Какое-то сообщение в консоль");  // привычные запросы $this->connection()->updateQuery()     ->table('users')     ->set(['role' => 'user'])     ->execute(); 

Кстати очень рекомендую в именах миграций писать краткое описание а не просто цифры. Поскольку используется порядок natsort то можно смело писать комент после знака _, например 33_fairies_table.sql

Тут сразу стоит ответить на 2 вопроса:

Почему нет down миграций для отката:
Если думать с точки зрения самой БД, то понятия отката нет как такого. Откат это просто еще одна миграция вперед, которая отменяет то что сделали предыдущие. К тому же такой откат не всегда даже возможен, так как если вы в одной миграции удалили таблицу, то откат мог бы ее воссоздать но уж никак не восстановить данные.

Почему изменения делаются сырыми SQL запросами а не универсальными методами типа createTable() ?
Проблема универсальных методов в том что они упускают тонкости в различиях разных баз, и много вещей приходится угадывать. К тому же возможен вариант когда библиотек обновится и начнет создавать поля и таблицы чуть по другому, и тогда продакшн база со старыми миграциями будет отличатся от новой где были запущены те же миграции несколько месяцев спустя. Плюс существует уже и так столько графических утилит для создания SQL для таблиц и конвертации с одной БД в другую, что делать хелпер методы для этого кажется довольно лишне.

Сиды

Сиды — это данные которыми можно наполнить базу. Например это могут быть какие-то дефолтные пользователи, категории товаров итд, также их можно использовать для наполнения базы тестовыми данными для функциональных тестов. Имя файла должно совпадать с именем таблицы, доступные форматы .php и .json. Например:

// /assets/migrate/seeds/fairies.php  <?php  return array(     array(         'id'   => 1,         'name' => 'Pixie'     ),     array(         'id'   => 2,         'name' => 'Trixie'     ), ); 
// /assets/migrate/seeds/flowers.json  [     {         "id": 1,         "name": "daisy"     },     {         "id": 2,         "name": "Rose"     }, ] 

В случае с .php кроме возвращения массива данных также есть возможность сделать все руками используя соединение с БД:

// /assets/migrate/seeds/fairies.php  <?php $this->connection()->insertQuery()     ->data([         'id'   => 1,         'name' => 'Pixie'      ])      ->execute(); 

Для вставки сидов используется команда framework:seed:

framework:seed [ --truncate ] [ CONFIG ]
Seed the database with data

Options:
truncate Truncate the tables before inserting the data.

Arguments:
CONFIG Seed configuration name, defaults to 'default'

Если в таблице уже существуют данные то это приведет к выводу ошибки. Для того чтобы очистить таблицу перед вставкой можно использовать параметр —truncate.

Очевидно что для одного и того же соединения с БД можно задать несколько профилей сидов в файле конфигурации.

Использование без фреймворка

Как и все другие компоненты PHPixie Migrate можно использовать отдельно от фреймворка, примерно вот так:

$slice = new \PHPixie\Slice(); $database = new \PHPixie\Database($slice->arrayData(array(     'default' => array(         'database' => 'phpixie',         'user'     => 'phpixie',         'password' => 'phpixie',         'adapter'  => 'mysql', // one of: mysql, pgsql, sqlite         'driver'   => 'pdo'     ) )));  $filesystem = new \PHPixie\Filesystem(); $migrate = new \PHPixie\Migrate(     $filesystem->root(__DIR__.'/assets/migrate'),     $database,     $slice->arrayData(array(     'migrations' => array(         'default' => array(             'connection' => 'default',             'path'       => 'migrations',         )     ),     'seeds' => array(         'default' => array(             'connection' => 'default',             'path' => 'seeds'         )     ) )));   $cli = new \PHPixie\CLI(); $console = new \PHPixie\Console($slice, $cli, $migrate->consoleCommands()); $console->runCommand(); 

Здесь имена команд будут run, seed, database без префикса framework.

Есть конечно еще несколько фич которые хотелось бы добавить, но надеюсь компонент понравится тем пользователям которые уже заждались миграций для 3-й PHPixie.
ссылка на оригинал статьи https://habrahabr.ru/post/315254/


Комментарии

Добавить комментарий

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