
Из этой статьи вы получите общее представление о миграциях, а также научитесь их создавать. Во второй же части, мы с вами увидим, как легко они могут быть интегрированы в ваше приложение.
Данная статья будет полезна начинающим пользователям CodeIgniter, но я надеюсь что и более продвинутые коллеги узнают об этой чудесной библиотеке и подчерпнут для себя что-нибудь новое.
Кроме всего прочего, данная библиотека совсем не сложна, и реализовать ее при желании для любой другой платформы не составит большого труда!
Обзор библиотеки
Библиотека Migration позволяет нам хранить в приложении все изменения базы данных, и накатывать или откатывать их при необходимости. Это может быть удобно и для разработки в команде — не надо объяснять вашему коллеге, что надо изменить в базе, чтобы ваш код заработал, так и при выгрузке новых версий сайта на боевой сервер. Ну или, на худой конец, можно всегда быстро откатиться до старой версии, если вы где-то напортачили.
Чтобы понять в общих чертах, как работает библиотека рассмотрим следующий примитивный сценарий:
0. Допустим, у нас есть 0 версия приложения с начальной базой (также версии 0).
1. В ходе разработки мы понимаем, что для реализации нового функционала (например системы подписки на новости) нам необходимо будет внести изменения не только в код приложения, но и в структуру базы данных.
2. Для этого мы в конфиге укажем, что версия базы данных для этой версии кода будет 1 и вместе с новым кодом создадим миграцию 001, указав для нее действия как для апгрейда, так и для даунгрейда базы (на случай если нужно будет откатить версию приложения).
3. Затем мы реализуем какой-либо механизм накатывания обновлений — это может быть и страничка в админке, и решение, использующее CLI, или даже полностью автоматическое обновление при выгрузке из системы контроля версий.
4. Выгружаем новый код проекта на сайт, запускаем миграцию до нужной версии, и вуаля!
А теперь представьте, что вам нужно обновить приложение через 3 версии вперед, или же на тестовом сервере посмотреть как была реализована версия, сделанная пару месяцев назад? Легко, просто изменив код, мигрируйте до нужной версии базы (миграция произойдет постепенно, допустим с 4-й до 1-й сначала накатятся 3-я и 2-я, а затем 1-я версии)!
Вы воодушевились такой возможностью как и я и хотите попробовать? Нет ничего проще!
Практическое использование
Собственно говоря, библиотека совершенно проста в использовании, и для ее внедрения в проект требуется добавить\поправить совсем немного строчек кода.
Весь процесс создания миграций не займет десяток минут времени, а сэкономит вам и вашим коллегам, работающим над этим же проектом прилично.
Создаем класс MY_Migration
Итак, для начала нам будет нужно немного
Зачем? Все очень просто, по умолчанию этот класс не умеет сообщать о том, какие версии базы и кода являются текущими, а реализовывать эти проверки по всему коду не совсем правильно, лучше это сделать в одном месте.
Для этого воспользуемся стандартной методикой расширения классов, используемой в CodeIgniter — создадим файл %site_path%/application/libraries/MY_Migration.php со парой десятков строк кода внутри.
Этот класс добавит к реализации предка еще 2 публичных метода:
/**
* Wrapper function for the protected _get_version.
* Get's the database current version
*
* @access public
* @return integer Current DB Migration version
*/
public function get_db_version() {
return parent::_get_version();
}
/**
* Retrieves current file system version
*
* @access public
* @return integer Current file system Migration version
*/
public function get_fs_version() {
return $this->_migration_version;
}
Примечание: здесь и далее могут быть приведены сокращенные листинги кода, ссылка на все файлы, использованные в туториале в конце статьи
Как видите, функции являются лишь обертками для protected метода для получения версии базы данных и опять же protected свойства $_migration_version, и вполне наглядно демонстрируют применение инкапсуляции.
Также советую обратить внимание на важный момент: в оригинальном классе Migration стоит ограничение, из-за которого его конструктор выполняется только при инициализации родительского класса.
Поэтому чтобы приложение работало правильно, автоматически инициализируя MY_Migration вместо оригинала, необходимо продублировать конструктор родительского класса, изменив в нем условие на 41 строке:
public function __construct($config = array()) {
# Only run this constructor on main library load
if (get_parent_class($this) !== FALSE)
{
return;
}
### Other code here...
}
на
public function __construct($config = array()) {
# Only run this constructor on main library load
if (get_parent_class($this) !== FALSE && get_class($this)!='MY_Migration')
{
return;
}
### Other code here...
}
Создаем миграцию
Расширив базовый класс, дело остается за малым. Для того, чтобы библиотека могла накатывать или откатывать изменения на базу данных, необходимо создать миграционный файл, содержащий в себе класс-потомок Migration(в нашем случае MY_Migration).
Так как у нас это первая миграция, то создадим следующий файл: %site_path%/application/migrations/001_add_messages.php, содержащий в себе фунции up и down:
<?php defined('BASEPATH') OR exit('No direct script access allowed');
class Migration_Add_messages extends MY_Migration {
public function up() {
$this->db->query("
CREATE TABLE IF NOT EXISTS `email_list` (
`list_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`email` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
) ENGINE=MyISAM;");
}
public function down() {
$this->db->query("DROP TABLE IF EXISTS `email_list`");
}
}
Обратите внимание на то, что файлы с миграциями содержат в начале 3-х здачный цифровой порядковый номер версии, на которую они переводят базу данных, а класс, содержащийся в них называется как имя файла, где вместо номера версии стоит Migration_.
Правим конфиг
Наконец, для работы с миграциями нужно немного подправить конфиг в файле %site_path%/application/config/migration.php и включить их, посмотреть правильно ли указаны к ним путь и версия базы данных, требуемой для корректной работы нашего кода (стандартные комментарии вырезаны из листинга):
$config['migration_enabled'] = TRUE;
$config['migration_version'] = 1;
$config['migration_path'] = APPPATH . 'migrations/';
Обратите внимание, что я указал 1-ю версию, что подразумевает, что мы уже сделали функционал рассылок.
Итог
Таким образом, мы немного повысили удобство пользования библиотекой, расширив ее функционал, обошли подводный камень, связанный с проверкой в конструкторе на наследование оригинального класса, а так же научились создавать миграции.
Как вы видите, ничего сложного в создании миграций нет, а, повторюсь, они могут сэкономить вам существенное количество времени. Более того, их внедрение в текущий проект так же не должно вызвать каких-либо сложностей. Кстати, как раз внедрению и будет посвящена моя вторая статья, которая появится в самое ближайшее время.
Скачать архив с полными исходниками
Вторая часть: Миграции баз данных — интеграция с вашим приложением
PS:
UPD: Добрые анонимы налили немного кармы, перенес в блог CodeIgniter