Миграция - это набор изменений, либо обновляющий схему, либо возвращающий ее к предыдущему состоянию. Пустая миграция генерируется следующими командами:
cd APP_DIR
./vendor/bin/doctrine-module migrations:generate
Эти команды назначают каталог приложения текущим рабочим каталогом и затем выполняют
консольную команду migrations:generate.
DoctrineModuleиDoctrineORMModuleпредоставляют несколько консольных команд, которые можно использовать для различных задач, связанных с поддержкой базы данных (например, генерации или выполнения миграций). Список доступных команд можно посмотреть с помощью командыlist:
./vendor/bin/doctrine-module list
После запуска команды migrations:generate созданную миграцию можно будет найти под каталогом APP_DIR/data/Migrations.
Имя файла миграции имеет вид VersionYYYYMMDDHHIISS.php, где YYYY - текущий год, MM - текущий месяц, DD - текущий день,
а HH, II и SS - соответственно текущие час, минута и секунда.
Если вы откроете созданный файл, то увидите следующее содержимое:
<?php
namespace Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
/**
* Автоматически сгенерированная миграция: измените под ваши нужды!
*/
class Version20160901114333 extends AbstractMigration
{
/**
* @param Schema $schema
*/
public function up(Schema $schema)
{
// эта миграция up() сгенерирована автоматически, пожалуйста, измените ее под свои нужды
}
/**
* @param Schema $schema
*/
public function down(Schema $schema)
{
// эта миграция down() сгенерирована автоматически, пожалуйста, измените ее под свои нужды
}
}
Если вы не видите созданную миграцию в NetBeans, откройте меню Source и выберите пункт меню Scan for external changes.
Как видите из фрагмента кода выше, миграция - это обычный PHP-класс, наследуемый от базового класса Doctrine\DBAL\Migrations\AbstractMigration.
У каждой миграции должно быть по крайней мере два метода: up() and down(). Метод up() обновляет схему до нового состояния,
а метод down() возвращает к предыдущему. Оба этих метода принимают один аргумент типа Doctrine\DBAL\Schema\Schema, который можно
использовать для фактического изменения схемы базы данных.
Класс
Schemaявляется частью компонентаDoctrine\DBAL. За дополнительной информацией о предоставляемых им методах обратитесь к документации DBAL. Либо, что даже лучше, посмотрите на код внутри каталогаvendor/doctrine/dbal.
Класс миграции может иметь следующие (переопределенные) методы (таблица 13.1):
| Метод | Описание |
|---|---|
isTransactional() |
Если эта функция возвращает true (по умолчанию), вся миграция будет выполнена как одна транзакция; иначе, каждый из SQL-запросов миграции будет выполнен отдельно. |
getDescription() |
Этот метод должен возвращать строку, описывающую миграцию (с какой целью сделано это изменение схемы) |
preUp(Schema $schema) |
Этот метод будет выполнен перед обновлением схемы. |
postUp(Schema $schema) |
Этот метод будет выполнен после обновления схемы. |
preDown(Schema $schema) |
Этот метод будет выполнен перед возвратом схемы к предыдущему состоянию. |
postDown(Schema $schema) |
Этот метод будет выполнен после возврата схемы к предыдущему состоянию. |
Базовый класс AbstractMigration также предоставляет следующие полезные методы (таблица 13.2):
| Метод | Описание |
|---|---|
addSql($sql, array $params = [], array $types = []) |
Этот метод позволяет выполнить произвольный SQL-запрос. |
write($message) |
Этот метод помощника выводит сообщение (поясняющее или об отладке) на экран. |
throwIrreversibleMigrationException($message = null) |
Этот метод помощника, как правило, вызывается внутри метода down(), чтобы сообщить, что миграцию нельзя отменить. |
Как видите из таблицы 13.2, вы также можете изменить схему, вызвав метод addSql(). Этот метод можно
использовать для создания таблицы, ее обновления или удаления. Кроме того, его можно использовать, например,
для вставки каких-либо данных в таблицы (однако, вставка данных не является изменением схемы).
Миграции Doctrine предназначены для изменений схемы, а не для добавления данных в базу. Впрочем, вставка начальных данных в некоторых случаях весьма полезна.
Теперь, когда вы знаете, как создать миграцию, давайте создадим пару миграций для нашего приложения Blog.
Начальная миграция будет первой, которую мы создадим. Она будет применена к схеме пустой базы данных
и создаст четыре таблицы: post, comment, tag и post_tag.
Измените созданный нами в предыдущем разделе класс миграции, чтобы он выглядел, как показано ниже:
<?php
namespace Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
/**
* Класс миграции. Он либо обновляет схему БД (приводит к новому состоянию), либо
* возвращает ее к предыдущему состоянию.
*/
class Version20160901114333 extends AbstractMigration
{
/**
* Возвращает описание этой миграции.
*/
public function getDescription()
{
$description = 'This is the initial migration which creates blog tables.';
return $description;
}
/**
* @param Schema $schema
*/
public function up(Schema $schema)
{
// Создаем таблицу 'post'
$table = $schema->createTable('post');
$table->addColumn('id', 'integer', ['autoincrement'=>true]);
$table->addColumn('title', 'text', ['notnull'=>true]);
$table->addColumn('content', 'text', ['notnull'=>true]);
$table->addColumn('status', 'integer', ['notnull'=>true]);
$table->addColumn('date_created', 'datetime', ['notnull'=>true]);
$table->setPrimaryKey(['id']);
$table->addOption('engine' , 'InnoDB');
// Создаем таблицу 'comment'
$table = $schema->createTable('comment');
$table->addColumn('id', 'integer', ['autoincrement'=>true]);
$table->addColumn('post_id', 'integer', ['notnull'=>true]);
$table->addColumn('content', 'text', ['notnull'=>true]);
$table->addColumn('author', 'string', ['notnull'=>true, 'lenght'=>128]);
$table->addColumn('date_created', 'datetime', ['notnull'=>true]);
$table->setPrimaryKey(['id']);
$table->addOption('engine' , 'InnoDB');
// Создаем таблицу 'tag'
$table = $schema->createTable('tag');
$table->addColumn('id', 'integer', ['autoincrement'=>true]);
$table->addColumn('name', 'string', ['notnull'=>true, 'lenght'=>128]);
$table->setPrimaryKey(['id']);
$table->addOption('engine' , 'InnoDB');
// Создаем таблицу 'post_tag'
$table = $schema->createTable('post_tag');
$table->addColumn('id', 'integer', ['autoincrement'=>true]);
$table->addColumn('post_id', 'integer', ['notnull'=>true]);
$table->addColumn('tag_id', 'integer', ['notnull'=>true]);
$table->setPrimaryKey(['id']);
$table->addOption('engine' , 'InnoDB');
}
/**
* @param Schema $schema
*/
public function down(Schema $schema)
{
$schema->dropTable('post_tag');
$schema->dropTable('tag');
$schema->dropTable('comment');
$schema->dropTable('post');
}
}
Во фрагменте кода выше находятся три метода:
getDescription(), предоставляющий описание миграции.up() обновляет схему, добавляя новые таблицы.down() удаляет таблицы, тем самым возвращая схему к ее предыдущему состоянию.Теперь, предположим, мы решили повысить производительность нашей базы данных, добавив к таблицам индексы.
Если вы хотите более детально узнать о индексах баз данных и о том, почему они так полезны, можете обратиться к отличному руководству Use the Index, Luke.
Кроме того, мы можем повысить целостность данных, добавив внешние ключи. Для этого нужно добавить еще одну миграцию.
Сгенерируйте пустую миграцию с помощью консольной команды migrations:generate. Измените код следующим образом:
<?php
namespace Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
/**
* Класс миграции. Он либо обновляет схему БД (приводит к новому состоянию), либо
* возвращает ее к предыдущему состоянию.
*/
class Version20160901114938 extends AbstractMigration
{
/**
* Возвращает описание этой миграции.
*/
public function getDescription()
{
$description = 'This migration adds indexes and foreign key constraints.';
return $description;
}
/**
* @param Schema $schema
*/
public function up(Schema $schema)
{
// Добавляем индекс к таблице post
$table = $schema->getTable('post');
$table->addIndex(['date_created'], 'date_created_index');
// Добавляем индекс и внешний ключ к таблице comment
$table = $schema->getTable('comment');
$table->addIndex(['post_id'], 'post_id_index');
$table->addForeignKeyConstraint('post', ['post_id'], ['id'], [], 'comment_post_id_fk');
// Добавляем индексы и внешние ключи к таблице post_tag table
$table = $schema->getTable('post_tag');
$table->addIndex(['post_id'], 'post_id_index');
$table->addIndex(['tag_id'], 'tag_id_index');
$table->addForeignKeyConstraint('post', ['post_id'], ['id'], [], 'post_tag_post_id_fk');
$table->addForeignKeyConstraint('tag', ['tag_id'], ['id'], [], 'post_tag_tag_id_fk');
}
/**
* @param Schema $schema
*/
public function down(Schema $schema)
{
$table = $schema->getTable('post_tag');
$table->removeForeignKey('post_tag_post_id_fk');
$table->removeForeignKey('post_tag_tag_id_fk');
$table->dropIndex('post_id_index');
$table->dropIndex('tag_id_index');
$table = $schema->getTable('comment');
$table->dropIndex('post_id_index');
$table->removeForeignKey('comment_post_id_fk');
$table = $schema->getTable('post');
$table->dropIndex('date_created_index');
}
}
Созданные нами миграции вы можете найти в примере Blog, который идет вместе с этой книгой.