Недавно восторженные апологеты «yii» опубликовали новость о том что теперь их фреймворк поддерживает миграции к базе данных. Имея опыт работы с миграциями в doctrine, я давно уже задумывался об использовании миграций в кохане. И решил что настал момент самостоятельно во всём разобраться.

Если вы не знаете что такое миграции к базе данных, то вот вам небольшая теория.

Теория про Петю и Васю и миграции

Допустим Вася и Петя работают над одной программой — веб-сайтом для хомячков.

В новой функции Пети требуется создать и использовать новую таблицу в БД. А Васе необходимо расширить пару таблиц уже существующих, добавив туда два поля и создать новый индекс.

Так как Петя не знаком с миграциями, и для того что бы показать Васе о том что у него изменилась схема БД, он делает дамп структуры базы данных и сохраняет его в особом файле «dump.sql», в надежде на то что Вася заметит изменения в этом файле и самостоятельно обновит структуру своей БД.

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

Теперь представим, что Вася знает о миграциях, поэтому он составляет специальные файлы и коммитит их в общий репозитарий.

Файлы представляют из себя инструкции DQL. Например вот такие (может и не совсем такие, но подобные):

class 001_Migration_Extends_Table extend Migration
{
    public function up()
    {
         $this->table('table_one')->add_column('sort', 'integer', 'notnull');
         $this->table('table_two')->edit_column('name', 'varchar', 255);
         $this->table('table_one')->add_index('sort', 'index');
    }

    public function down()
    {
        $this->table('table_one')->remove_column('sort');
        $this->table('table_two')->edit_column('name', 'varchar', 100);
        $this->table('table_one')->remove_index('sort');
    }
}

Если начать разобирать этот псевдокод, то мы увидим, что есть две функции up и down. Которые отвечают за накатывание изменений на базу и соответственно — откатывание того что сделали.

По этому коду можно сразу понять что произошло и что мы хотели сделать.

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

./kohana migration/up

Модули миграций в Kohana 3

На просторах интернета нашлось аж сразу несколько реализаций миграций для KO3.

kohana-3-migrations

Первая, и самая лёгкая — kohana-3-migrations

Крайне простая в использовании. Вся суть которой состоит в том, что вместо псевдоязыка описания изменений, используется синтаксис SQL (DQL).

Список файлов с инструкциями:

001_Base_DOWN.sql
001_Base_UP.sql
002_Fixtures_DOWN.sql
002_Fixtures_UP.sql

Которые содержат в себе примерно такой код (001_Base_UP.sql):

CREATE TABLE `providers` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `name` varchar(500) NOT NULL,
  `description` text NOT NULL,
  `accepted` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `user_idx` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

и вот такой, соответственно (001_Base_DOWN.sql):

DROP TABLE IF EXISTS `providers`;

Это лучше чем ничего, но и самый верный способ прострелить себе ногу.

migration

Вторая и достаточно мощная система — migration Библиотека зависит от модуля DQL — DBForge

Имеет драйвера для ORM Sprig и Jelly, и возможность написать собственные драйвера.

К сожалению документации к этому модулю крайне мало, и всё взаимодействие с БД скрыто за огромным слоем абстракции. К тому же, модули для этих библиотек с лета не обновлялись.

Вкратце это выглядит так:
Вы вызываете нужный контроллер, который уже дёргает модель наследущую интерфейс миграций.

$migration = Migration::factory('user', 'jelly');
$migration->sync();

В коде которой используется библиотека DBForge для создания DQL запросов

$dbforge = new Dbforge();
$fields = array
(
    'blog_id' => array
    (
        'type' => 'INT',
        'constraint' => 5,
        'unsigned' => TRUE,
        'auto_increment' => TRUE
    ),
    'blog_title' => array
    (
        'type' => 'VARCHAR',
        'constraint' => '100',
    ),
    'blog_author' => array
    (
        'type' =>'VARCHAR',
        'constraint' => '100',
        'default' => 'King of Town',
    ),
    'blog_description' => array
    (
        'type' => 'TEXT',
        'null' => TRUE,
    ),
);
$dbforge->add_field($fields);

// Add primary key
$dbforge->add_key('blog_id', TRUE);

Если вы работайте с этим модулем, пожалуйста поделитесь в комментариях своим мнением о нём.

kohana-migrations

И ещё одна замечательная реализация построенная на библиотеке doctrine2. Плюсы и минусы тут кроются в использовании ORM библиотеки dostrine2 из фреймворка symfony2.

В частности:
— Использование YAML для описания моделей
— Использование модуля «Console» из этого же фреймворка
— Отличный ORM движок
— Чужеродный код (хоть и хорошо написанный и спроектированный)
— Подключение внешних зависимых модулей

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

А чем пользуйтесь вы, работая в команде?