Миграция - это набор изменений, либо обновляющий схему, либо возвращающий ее к предыдущему состоянию. Пустая миграция генерируется следующими командами:
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, который идет вместе с этой книгой.