Статьи

Создание версий базы данных с лестничными миграциями

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

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

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

Многие основные фреймворки имеют свою собственную миграционную реализацию, но для тех, кто ее не использует — и если вы не используете какую-либо фреймворк — есть Ladder.

Представляя Лестница

Ladder — это инструмент для создания, запуска и управления миграциями баз данных. Миграция — это просто класс PHP, и поэтому ее можно включить в контроль версий вместе с остальным кодом вашего приложения.

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

Миграции всегда выполняются в последовательности. Итак, предположим, что вы пишете один для создания таблицы products , а через несколько недель создаете новую миграцию, чтобы добавить в нее дополнительный столбец. Попытка запустить последний до того, как первый вызовет ошибку. Ladder решает эту проблему путем последовательной нумерации миграций, а также сохранения записи о том, какие миграции были выполнены (и когда) в самой базе данных.

Установка

Лестница может быть загружена из Bitbucket или через Composer . Однако для запуска и запуска требуется несколько шагов.

Самый простой — хотя и, по общему признанию, наименее элегантный — способ установить его — это загрузить или клонировать его и поместить в каталог под названием ladder в корневом каталоге вашего проекта. Проблема с использованием Composer заключается в том, что при запуске composer update Composer ваши файлы конфигурации будут перезаписаны.

Существует пять файлов конфигурации, каждый из которых должен быть создан вручную; Самый простой способ — скопировать приведенные примеры:

 cp ladder/config/config.php.example ladder/config/config.php cp ladder/config/database.php.example ladder/config/database.php cp ladder/config/diff.php.example ladder/config/diff.php cp ladder/config/editor.php.example ladder/config/editor.php cp ladder/config/table.php.example ladder/config/table.php 

Вероятно, вам нужно всего лишь изменить editor.php database.php который содержит сведения о соединении с базой данных, и editor.php , в котором вы можете указать предпочитаемый текстовый редактор, а также выбрать автоматическое открытие новых миграций после создания.

Создание миграции

Давайте начнем с создания миграции для создания таблицы users .

В командной строке:

 php ladder/ladder.php create create_users_table 

Это создаст файл с именем ladder/migrations/00001_create_users_table , который по умолчанию содержит базовую структуру с некоторыми примерами закомментированных вызовов. Если вы установили для auto-edit значение true в ladder/config/editor.php , этот файл сразу же откроется в указанном текстовом редакторе. Вы можете называть миграцию как угодно, но полезно сразу увидеть, что делает миграция из своего имени файла.

Вот как может выглядеть этот файл (для ясности я удалил закомментированные строки):

 class Create_Users_Table_Migration_00001 extends Migration { protected $min_version = '0.8.1'; public function up() { $this->create_table('users') ->column('email', 'varchar', array('limit' => 128, 'null' => FALSE)) ->column('password', 'varchar', array('limit' => 32, 'null' => FALSE)); } public function down() { $this->table('users')->drop(); } } 

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

Метод create_table() возвращает ссылку на новую таблицу, а в классе Table есть метод column() для добавления нового столбца. Он имеет свободный интерфейс, поэтому вы можете связать их вместе, чтобы создать несколько столбцов одновременно. Вы заметите, что столбца ID нет — он создается автоматически — то есть, автоинкрементный первичный ключ на основе целых чисел, называемый id .

table() возвращает ссылку на таблицу, но также создает ее, если она еще не существует, поэтому вы можете смело изменять вызов create_table() на table()

Давайте создадим еще одну миграцию, на этот раз для создания таблицы roles :

 php ladder/ladder.php create create_roles_table 

Сам файл:

 class Create_Roles_Table_Migration_00002 extends Migration { protected $min_version = '0.8.1'; public function up() { $this->table('roles') ->column('nme', 'varchar', array('limit' => 128, 'null' => FALSE)); } public function down() { $this->table('roles')->drop(); } } 

Теперь вы захотите запустить миграцию. Для этого:

 php ladder/ladder.php migrate 

Если вы посмотрите в базу данных, вы найдете четыре таблицы:

migrations создаются автоматически и используются для отслеживания выполненных миграций.
migrations_kvdata также создан для вас, и может быть использован для произвольного хранения ключа / значения вашими миграциями
users и roles — это таблицы, которые мы только что добавили.

Однако если вы обратили пристальное внимание на миграцию ролей, то заметите, что в ней создан столбец с именем nme вместо name . На этом этапе мы можем исправить это, «отменив» миграцию, изменив класс и снова запустив его. Чтобы откатить миграцию:

 php ladder/ladder.php remove 2 

Число 2 указывает, на какую миграцию выполнить откат — это префикс имени файла миграции без начальных нулей.

Теперь вы можете просто внести исправление и снова запустить миграцию:

 php ladder/ladder.php migrate 

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

Есть также более быстрый способ, используя вместо этого reapply :

 php ladder/ladder.php reapply 2 

Это вызовет второй метод down() миграции, а затем метод up() , все за один раз.

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

 php ladder/ladder.php create add_status_to_users_table 

Миграция будет выглядеть примерно так:

 class Add_Status_To_Users_Table_Migration_00003 extends Migration { protected $min_version = '0.8.1'; public function up() { $this->table('users') ->column('status', 'integer', array('null' => FALSE, 'default' => 0)); } public function down() { $this->table('users')->drop_column('status'); } } 

Как и раньше, запустите с:

 php ladder/ladder.php migrate 

Теперь, если вы проверите свою базу данных, вы увидите, что в таблице users появился новый столбец.

Заполнение базы данных

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

Например, вы можете расширить миграцию create_users_table для создания учетной записи пользователя root по умолчанию:

 public function up() { // as before $root_user_id = $this->table('users') ->insert(array( 'email' => '[email protected]', 'password' => NULL, )) ->insert_id; $this->set('root_user_id', $root_user_id); } public function down() { // as before if ((bool) $user_id = $this->get('root_user_id')) { $this->table('users')->delete(array( 'id' => (int) $user_id, )); } } 

Обратите внимание, что мы используем методы set() и get() чтобы воспользоваться преимуществами хранилища ключей / значений Ladder, храня идентификатор пользователя, чтобы мы могли обратиться к нему позже.

Вы также можете импортировать данные из CSV-файлов в ваши миграции, например:

 $this->table('users')->import_csv('/path/to/users.csv'); 

Чтобы обновить, а не вставить данные CSV, вы должны сделать это:

 $this->table('users')->import_csv('/path/to/users.csv', TRUE, array('email')); 

В этом случае параметр send указывает, что мы хотим запустить UPDATE, а третий содержит список ключевых полей для определения, какие записи обновлять.

Добавление дополнительных баз данных

Вы заметите, что файл ladder/config/database.php по умолчанию ladder/config/database.php демонстрирует, как вы можете добавить дополнительные соединения с базой данных; возможно для постановки или живых баз данных. Например:

 $config['default'] = array( 'hostname' => 'localhost', // etc ); $config['staging'] = array( 'hostname' => 'server2.myreal.host.name', // etc ); $config['live'] = array( 'hostname' => 'server2.myreal.host.name', // etc ); 

Вы можете указать соединение для использования при запуске Ladder следующим образом:

 php ladder/ladder.php --config=live 

Дополнительные команды

Положение дел

Вы можете получить статус базы данных с помощью команды status :

 php ladder/ladder.php status 

Пример вывода:

 Migration Status Latest migration is 3 Connecting to localhost:3306... Connected. Server version 5.1.62. < ladder: 1 Completed in 0.285s 

diff и diff-save

Вы можете вывести состояние базы данных в файл с помощью команды diff-save :

 php ladder/ladder.php diff-save 

Это создаст файл, содержащий текущее состояние базы данных в виде сериализованного массива в ladder/cache/ladder . Теперь вы можете внести изменения в схему вручную, а затем вернуть базу данных обратно в локально сохраненное состояние с помощью команды diff :

 php ladder/ladder.php diff 

Версия

Наконец, вы можете получить версию Ladder, которую вы используете, с помощью следующей команды:

 php ladder/ladder.php version 

Резюме

В этой статье я представил Ladder для поддержки схем базы данных и предварительного заполнения данных. Чтобы узнать больше, взгляните на страницу Bitbucket и веб-сайт .