- PVSM.RU - https://www.pvsm.ru -
Вольно цитируя вступление к соответствующей статье на RailsGuides,
Миграции — это удобный способ управления структурой и изменениями схемы БД.
Конечно, можно вести дела по старинке, оперирую множеством SQL-файлов, или, о ужас!, редактируя куски SQL-кода в одном большом файле, который представляет собой актуальную схему БД.
Однако следить за этими изменениями, начиная с некоторого момента, становится очень сложно, не говоря уже о применении соответствующих изменений на продакшен-машине: тут нужно обладать ловкостью гепарда, силой медведя и мудростью всех восточных мудрецов, вместе взятых, чтобы все сделать правильно и ничего не уронить.
Но как быть, если Вы не обладаете какими-либо из вышеперечисленных качеств? Правильно, нужно систематизировать и автоматизировать процесс, переложив большую часть работы на машину.
Если Вы уже заинтересовались, или все еще не уверены, но перспектива иметь прозрачную историю изменений и возможность с помощью одной-двух консольных команд откатиться на любою версию схемы, звучит заманчиво, прошу под кат.
Начав работать с Ruby on Rails довольно быстро знакомишься с механизмом миграций, а уже через некоторое время не понимаешь, как можно вообще было обходиться без этого невероятно удобного инструмента.
Придя в проект, который разрабатывался на PHP, я постарался привнести в него хотя бы минимальный набор полезных инструментов, знакомых по опыту общения с Ruby on Rails. Одним из пунктов была система для поддержки миграций.
После некоторого поиска выбор был сделан в пользу Ruckusing Migrations [1], как наиболее похожего на то, что я видел в рельсах. Рапортую, что по прошествии более полугода полет нормальный!
Предполагается, что Вы используете Composer для управления зависимостями. Если нет, обязательно попробуйте, оно того стоит!
Также при желании Вы можете клонировать с GitHub репозиторий с примером: github.com/ArtemPyanykh/php_migrations_example [2]
Для начала добавьте в свой composer.json:
"require" : {
"ruckusing/ruckusing-migrations": "dev-master"
}
и выполните
~/dev/php_migrations_example(master)$ php composer.phar install
Composer подтянет Ruckusing Migrations и установит в директорию vendors
.
Далее, я советую поступить следующим образом:
.
└── db
├── logs
├── migrations
│ ├── main
│ ├── php_migrations_example -> main/
│ └── php_migrations_example_test -> main/
└── utility
В директории db
будут храниться Ваши миграции, конфиги и другие полезные штуки. Считайте этот каталог точкой отсчета для всего, что связано с миграциями.
Сами файлы с миграциями будут храниться в db/migrations/main
.
php_migrations_example
и php_migrations_example_test
— это названия девелоперской и тестовой баз данных.
Каталоги с соответствующими именами это просто символические ссылки на директорию main
, так как вряд ли у Вас будут разные миграции для разных окружений.
db/ruckus
со следующим содержимым:
#!/bin/bash
ruckus_dir="./../vendor/ruckusing/ruckusing-migrations"
if [ ! -d $ruckus_dir ]; then
echo "Ruckusing-Migrations wasn't detected. Please, use Composer to install the library."
exit
fi
if [ ! -f "ruckusing.conf.php" ]; then
echo "Ruckusing conf. file wasn't detected. Please, create proper ruckusing.conf.php."
exit
fi
if [ "$#" -lt 1 ]; then
echo "At least 1 argument required"
echo "See ./ruckus --help"
exit
fi
if [ "$1" == "--help" -o "$1" == "-h" ]; then
echo "Usage: ./ruckus [--help] <task-name> [<parameter1>[ <parameter2> [...]]]"
echo ""
echo "The available ruckus commands are:"
echo " ./ruckus db:migrate Ruckus scenario for tasks such as db:migrate, db:setup, etc."
echo " ./ruckus db:generate <migration_name> Ruckus scenarion for generating migration scaffolding"
echo ""
exit
fi
php $ruckus_dir"/ruckus.php" "$1" "${@:2}"
Это просто небольшой скрипт, который я позволил себе написать, дабы упростить работу с Ruckusing Migrations.
db/ruckusing.conf.php
:
<?php
//----------------------------
// DATABASE CONFIGURATION
//----------------------------
/*
Valid types (adapters) are Postgres & MySQL:
'type' must be one of: 'pgsql' or 'mysql'
*/
return array(
'db' => array(
'development' => array(
'type' => 'mysql',
'host' => 'localhost',
'port' => 3306,
'database' => 'php_migrations_example',
'user' => 'root',
'password' => 'root'
),
'test' => array(
'type' => 'mysql',
'host' => 'localhost',
'port' => 3306,
'database' => 'php_migrations_example_test',
'user' => 'root',
'password' => 'root'
)
),
'migrations_dir' => RUCKUSING_WORKING_BASE . '/migrations',
'db_dir' => RUCKUSING_WORKING_BASE . '/utility',
'log_dir' => RUCKUSING_WORKING_BASE . '/logs'
);
?>
Все, больше никаких настроек не требуется, Вы успешно интегрировали себе систему миграций!
В целом все очень просто. Давайте начнем с того, что сгенерируем миграцию:
~/dev/php_migrations_example(master)$ cd db
~/dev/php_migrations_example/db(master)$ ./ruckus db:generate CreateTestTable
Created migration: 20130508145210_CreateTestTable.php
Вы можете заметить, что в каталоге db/migrations/main после этого добавится файл примерно с таким же названием (timestamp будет другой) следующего содержания:
<?php
class CreateTestTable extends Ruckusing_Migration_Base
{
public function up()
{
}//up()
public function down()
{
}//down()
}
Миграции обладают тем свойством, что могут быть не только применены, но и отменены, если существует адекватный способ отката изменений. Именно такова семантика методов up() (применение изменений) и down() (откат изменений). Давайте создадим таблицу test с несколькими полями и парой индексов. Дополним файл следующим образом:
<?php
class CreateTestTable extends Ruckusing_Migration_Base
{
public function up()
{
$table = $this->create_table('test', array('options' => 'ENGINE=InnoDB DEFAULT CHARSET=utf8'));
$table->column('this', 'integer', array('unsigned' => true, 'null' => false, 'default' => '42'));
$table->column('that', 'string', array('limit' => '7'));
$table->column('those', 'datetime');
$table->finish();
$this->add_index('test', array('this', 'that'), array('unique' => true));
}//up()
public function down()
{
$this->drop_table('test');
}//down()
}
и запустим миграции:
~/dev/php_migrations_example/db(master)$ ./ruckus db:migrate
Started: 2013-05-08 7:05pm MSK
[db:migrate]:
Schema version table does not exist. Auto-creating.
Creating schema version table: schema_migrations
Migrating UP:
========= CreateTestTable ======== (0.31)
Finished: 2013-05-08 7:05pm MSK
Вы заметите, что помимо создания таблицы test, которая полностью соответствует описанной выше спецификации, также создалась таблица schema_migrations. Это нормально — именно здесь Ruckusing Migrations хранит информацию о том, какие миграции были применены, а какие не были.
Также просто можно откатиться или запустить миграции для другого окружения:
~/dev/php_migrations_example/db(master)$ ./ruckus db:migrate VERSION=-1
Started: 2013-05-08 7:13pm MSK
[db:migrate]:
Migrating DOWN:
========= CreateTestTable ======== (0.21)
Finished: 2013-05-08 7:13pm MSK
~/dev/php_migrations_example/db(master)$ ./ruckus db:migrate ENV=test
Started: 2013-05-08 7:14pm MSK
[db:migrate]:
Schema version table does not exist. Auto-creating.
Creating schema version table: schema_migrations
Migrating UP:
========= CreateTestTable ======== (0.24)
Finished: 2013-05-08 7:14pm MSK
Это лишь небольшая демонстрация возможностей системы. Однако, я думаю уже сейчас понятно, насколько проще и удобнее становится версионирование БД с применением правильного механизма миграций.
ruckus
не из директории db/
, то получите ошибку. Это связано с тем, что все пути в скрипте относительные, и при желании это легко исправляется. Нужно, однако, учесть один момент: по умолчанию, конфиг ищется в рабочей директории.
Автор: Deshene
Источник [5]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/php-2/33929
Ссылки в тексте:
[1] Ruckusing Migrations: https://github.com/ruckus/ruckusing-migrations
[2] github.com/ArtemPyanykh/php_migrations_example: https://github.com/ArtemPyanykh/php_migrations_example
[3] Percona Toolkit: http://www.percona.com/software/percona-toolkit
[4] getcomposer.org/: http://getcomposer.org/
[5] Источник: http://habrahabr.ru/post/179155/
Нажмите здесь для печати.