Миграции баз данных
===================

В ходе разработки и ведения баз данных приложений, которые управляют данными, структуры используемых баз данных развиваются, как и исходный код приложений. Например, при разработке приложения, в будущем может оказаться необходимой новая таблица; уже после того, как приложение будет развернуто в рабочем режиме (продакшене), также может быть обнаружено, что для повышения производительности запросов должен быть создан определённый индекс; и так далее.
В связи с тем, что изменение структуры базы данных часто требует изменение исходного кода, yii поддерживает так
называемую возможность *миграции баз данных*, которая позволяет отслеживать изменения в базах данных при помощи терминов *миграции баз данных*, которые являются системой контроля версий вместе с исходным кодом.

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

1. Илья создает новую миграцию (например, создается новая таблица или изменяется определение столбца и т.п.).
2. Илья фиксирует новую миграцию в системе управления версиями (например, в Git, Mercurial).
3. Алексей обновляет свой репозиторий из системы контроля версий и получает новую миграцию.
4. Алексей применяет миграцию к своей локальной базе данных, тем самым синхронизируя свою базу данных, для того чтобы отразить изменения, которые сделал Илья.

А следующие шаги показывают, как развернуть новый релиз с миграциями баз данных в рабочем режиме (продакшена):

1. Сергей создаёт новую версию проекта репозитория, которая содержит некоторые новые миграции баз данных.
2. Сергей обновляет исходный код на рабочем сервере до новой версии.
3. Сергей применяет любую из накопленных миграций баз данных в рабочую базу данных.

Yii предоставляет набор инструментов для миграций из командной строки, которые позволяют:

* создавать новые миграции;
* применять миграции;
* отменять миграции;
* применять миграции повторно;
* показывать историю и статус миграций;

Все эти инструменты доступны через команду `yii migrate`. В этом разделе мы опишем подробно, как выполнять различные задачи, используя эти инструменты. Вы также можете сами посмотреть как использовать каждый отдельный инструмент при помощи команды `yii help migrate`.

> Tip: Миграции могут не только изменять схему базы данных, но и приводить данные в соответствие с новой схемой, создавать иерархию RBAC или очищать кеш.


## Создание миграций <span id="creating-migrations"></span>

Чтобы создать новую миграцию, выполните следующую команду:

```
yii migrate/create <name>
```

Требуемый аргумент `name` даёт краткое описание новой миграции. Например, если миграция о создании новой таблицы с именем *news*, вы можете использовать имя `create_news_table` и выполнить следующую команду:

```
yii migrate/create create_news_table
```

> Note: Поскольку аргумент `name` будет использован как часть имени класса создаваемой миграции, он должен содержать только буквы, цифры и/или символы подчеркивания.

Приведенная выше команда создаст новый PHP класс с именем файла `m150101_185401_create_news_table.php` в директории `@app/migrations`. Файл содержит следующий код, который главным образом декларирует класс миграции `m150101_185401_create_news_table` со следующим каркасом кода:

```php
<?php

use yii\db\Migration;

class m150101_185401_create_news_table extends Migration
{
    public function up()
    {

    }

    public function down()
    {
        echo "m101129_185401_create_news_table cannot be reverted.\n";

        return false;
    }

    /*
    // Use safeUp/safeDown to run migration code within a transaction
    public function safeUp()
    {
    }

    public function safeDown()
    {
    }
    */
}
```

Каждая миграция базы данных определяется как PHP класс расширяющийся от [[yii\db\Migration]]. Имя класса миграции автоматически создается в формате `m<YYMMDD_HHMMSS>_<Name>` (`m<ГодМесяцДень_ЧасыМинутыСекунды>_<Имя>`), где

* `<YYMMDD_HHMMSS>` относится к UTC дате-времени при котором команда создания миграции была выполнена.
* `<Name>` это то же самое значение аргумента `name` которое вы прописываете в команду.

В классе миграции, вы должны прописать код в методе `up()` когда делаете изменения в структуре базы данных.
Вы также можете написать код в методе `down()`, чтобы отменить сделанные `up()` изменения. Метод `up` вызывается для обновления базы данных с помощью данной миграции, а метод `down()` вызывается для отката изменений базы данных.
Следующий код показывает как можно реализовать класс миграции, чтобы создать таблицу `news`:

```php
<?php

use yii\db\Schema;
use yii\db\Migration;

class m150101_185401_create_news_table extends Migration
{
    public function up()
    {
        $this->createTable('news', [
            'id' => Schema::TYPE_PK,
            'title' => Schema::TYPE_STRING . ' NOT NULL',
            'content' => Schema::TYPE_TEXT,
        ]);
    }

    public function down()
    {
        $this->dropTable('news');
    }
}
```

> Info: Не все миграции являются обратимыми. Например, если метод `up()` удаляет строку из таблицы, возможно что у вас уже не будет возможности вернуть эту строку методом `down()`. Иногда Вам может быть просто слишком лень реализовывать метод `down()`, в связи с тем, что это не очень распространено - откатывать миграции базы данных. В этом случае вы должны в методе `down()` вернуть `false`, чтобы указать, что миграция не является обратимой.

Базовый класс миграций [[yii\db\Migration]] предоставляет подключение к базе данных через свойство [[yii\db\Migration::db|db]]. Вы можете использовать его для манипулирования схемой базы данных используя методы описанные в [работе со схемой базы данных](db-dao.md#database-schema).

Вместо использования физических типов данных, при создании таблицы или столбца, следует использовать *абстрактные типы* для того, чтобы ваша миграция являлась независимой от конкретной СУБД. Класс [[yii\db\Schema]] определяет набор констант для предоставления поддержки абстрактных типов. Эти константы называются в следующем формате `TYPE_<Name>`. Например,
`TYPE_PK` относится к типу автоинкремента (AUTO_INCREMENT) первичного ключа;
`TYPE_STRING` относится к строковому типу.
Когда миграция применяется к конкретной базе данных, абстрактные типы будут переведены в соответствующие физические типы.
В случае с MySQL, `TYPE_PK` будет превращено в `int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY`, а `TYPE_STRING` станет `varchar(255)`.

Вы можете добавить дополнительные ограничения при использовании абстрактных типов. В приведенном выше примере, ` NOT NULL` добавляется к `Schema::TYPE_STRING` чтобы указать, что столбец не может быть `NULL`.

> Info: Сопоставление абстрактных типов и физических типов определяется свойством [[yii\db\QueryBuilder::$typeMap|$typeMap]] в каждом конкретном `QueryBuilder` классе.

Начиная с версии 2.0.6, появился новый построитель схем, который является более удобным инструментом для описания структуры столбцов.
Теперь, при написании миграций, можно использовать такой код:

```php
<?php

use yii\db\Migration;

class m150101_185401_create_news_table extends Migration
{
    public function up()
    {
        $this->createTable('news', [
            'id' => $this->primaryKey(),
            'title' => $this->string()->notNull(),
            'content' => $this->text(),
        ]);
    }

    public function down()
    {
        $this->dropTable('news');
    }
}
```

Весь список методов описания типов столбцов доступен в API документации [[yii\db\SchemaBuilderTrait]].

## Генерация миграций <span id="generating-migrations"></span>

Начиная с версии 2.0.7 появился удобный способ создания миграций из консоли.

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

### Создание таблицы

```php
yii migrate/create create_post_table
```

сгенерирует

```php
class m150811_220037_create_post_table extends Migration
{
    public function up()
    {
        $this->createTable('post', [
            'id' => $this->primaryKey()
        ]);
    }

    public function down()
    {
        $this->dropTable('post');
    }
}
```

Чтобы сразу создать поля таблицы, укажите их через опцию `--fields`.

```php
yii migrate/create create_post_table --fields=title:string,body:text
```

сгенерирует

```php
class m150811_220037_create_post_table extends Migration
{
    public function up()
    {
        $this->createTable('post', [
            'id' => $this->primaryKey(),
            'title' => $this->string(),
            'body' => $this->text()
        ]);
    }

    public function down()
    {
        $this->dropTable('post');
    }
}
```

Можно указать дополнительные параметры.

```php
yii migrate/create create_post_table --fields=title:string(12):notNull:unique,body:text
```

сгенерирует

```php
class m150811_220037_create_post_table extends Migration
{
    public function up()
    {
        $this->createTable('post', [
            'id' => $this->primaryKey(),
            'title' => $this->string(12)->notNull()->unique(),
            'body' => $this->text()
        ]);
    }

    public function down()
    {
        $this->dropTable('post');
    }
}
```

> Note: первичный ключ добавляется автоматически и по умолчанию называется `id`. Если вам необходимо другое имя,
> указать его можно через опцию `--fields=name:primaryKey`.

### Внешние ключи

Начиная с версии 2.0.8, генератор поддерживает создание внешних ключей через ключевое слово `foreignKey`.

```php
yii migrate/create create_post_table --fields="author_id:integer:notNull:foreignKey(user),category_id:integer:defaultValue(1):foreignKey,title:string,body:text"
```

сгенерирует

```php
/**
 * Handles the creation for table `post`.
 * Has foreign keys to the tables:
 *
 * - `user`
 * - `category`
 */
class m160328_040430_create_post_table extends Migration
{
    /**
     * {@inheritdoc}
     */
    public function up()
    {
        $this->createTable('post', [
            'id' => $this->primaryKey(),
            'author_id' => $this->integer()->notNull(),
            'category_id' => $this->integer()->defaultValue(1),
            'title' => $this->string(),
            'body' => $this->text(),
        ]);

        // creates index for column `author_id`
        $this->createIndex(
            'idx-post-author_id',
            'post',
            'author_id'
        );

        // add foreign key for table `user`
        $this->addForeignKey(
            'fk-post-author_id',
            'post',
            'author_id',
            'user',
            'id',
            'CASCADE'
        );

        // creates index for column `category_id`
        $this->createIndex(
            'idx-post-category_id',
            'post',
            'category_id'
        );

        // add foreign key for table `category`
        $this->addForeignKey(
            'fk-post-category_id',
            'post',
            'category_id',
            'category',
            'id',
            'CASCADE'
        );
    }

    /**
     * {@inheritdoc}
     */
    public function down()
    {
        // drops foreign key for table `user`
        $this->dropForeignKey(
            'fk-post-author_id',
            'post'
        );

        // drops index for column `author_id`
        $this->dropIndex(
            'idx-post-author_id',
            'post'
        );

        // drops foreign key for table `category`
        $this->dropForeignKey(
            'fk-post-category_id',
            'post'
        );

        // drops index for column `category_id`
        $this->dropIndex(
            'idx-post-category_id',
            'post'
        );

        $this->dropTable('post');
    }
}
```

Положение ключевого слова `foreignKey` в описании поля не изменяет сгенерированный код. Это значит, что:

- `author_id:integer:notNull:foreignKey(user)`
- `author_id:integer:foreignKey(user):notNull`
- `author_id:foreignKey(user):integer:notNull`

Генерируют один и тот же код.

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

В приведенном выше примере `author_id:integer:notNull:foreignKey(user)` будет генерировать поле `author_id` с внешним ключом на таблицу `user`, а `category_id:integer:defaultValue(1):foreignKey` сгенерирует поле `category_id` с внешним ключом на таблицу `category`.

Начиная с версии 2.0.11, ключевое слово `foreignKey` может принимать второй параметр, который следует указывать через пробел.
Этот параметр будет использован в качестве имени поля внешнего ключа.
В случае, если второй параметр не будет передан, то поле для внешнего ключа будет извлечено из схемы таблицы.
Тем не менее, это справедливо только в тех случаях, когда таблица имеется в базе данных, первичный ключ задан и не является составным.
В иных случаях будет использоваться имя по умолчанию `id`.

### Удаление таблицы

```php
yii migrate/create drop_post_table --fields=title:string(12):notNull:unique,body:text
```

сгенерирует

```php
class m150811_220037_drop_post_table extends Migration
{
    public function up()
    {
        $this->dropTable('post');
    }

    public function down()
    {
        $this->createTable('post', [
            'id' => $this->primaryKey(),
            'title' => $this->string(12)->notNull()->unique(),
            'body' => $this->text()
        ]);
    }
}
```

### Добавление столбца

Если имя миграции задано как `add_xxx_column_to_yyy_table`, файл будет содержать необходимые методы `addColumn` и `dropColumn`.

Для добавления столбца:

```php
yii migrate/create add_position_column_to_post_table --fields=position:integer
```

сгенерирует

```php
class m150811_220037_add_position_column_to_post_table extends Migration
{
    public function up()
    {
        $this->addColumn('post', 'position', $this->integer());
    }

    public function down()
    {
        $this->dropColumn('post', 'position');
    }
}
```

### Удаление столбца

Если имя миграции задано как `drop_xxx_column_from_yyy_table`, файл будет содержать необходимые методы `addColumn` и `dropColumn`.

```php
yii migrate/create drop_position_column_from_post_table --fields=position:integer
```

сгенерирует

```php
class m150811_220037_drop_position_column_from_post_table extends Migration
{
    public function up()
    {
        $this->dropColumn('post', 'position');
    }

    public function down()
    {
        $this->addColumn('post', 'position', $this->integer());
    }
}
```

### Добавление промежуточной таблицы

Если имя миграции задано как `create_junction_table_for_xxx_and_yyy_tables`, файл будет содержать код для создания промежуточной таблицы.

```php
yii migrate/create create_junction_table_for_post_and_tag_tables
```

сгенерирует

```php
/**
 * Handles the creation for table `post_tag`.
 * Has foreign keys to the tables:
 *
 * - `post`
 * - `tag`
 */
class m160328_041642_create_junction_table_for_post_and_tag_tables extends Migration
{
    /**
     * {@inheritdoc}
     */
    public function up()
    {
        $this->createTable('post_tag', [
            'post_id' => $this->integer(),
            'tag_id' => $this->integer(),
            'created_at' => $this->dateTime(),
            'PRIMARY KEY(post_id, tag_id)',
        ]);

        // creates index for column `post_id`
        $this->createIndex(
            'idx-post_tag-post_id',
            'post_tag',
            'post_id'
        );

        // add foreign key for table `post`
        $this->addForeignKey(
            'fk-post_tag-post_id',
            'post_tag',
            'post_id',
            'post',
            'id',
            'CASCADE'
        );

        // creates index for column `tag_id`
        $this->createIndex(
            'idx-post_tag-tag_id',
            'post_tag',
            'tag_id'
        );

        // add foreign key for table `tag`
        $this->addForeignKey(
            'fk-post_tag-tag_id',
            'post_tag',
            'tag_id',
            'tag',
            'id',
            'CASCADE'
        );
    }

    /**
     * {@inheritdoc}
     */
    public function down()
    {
        // drops foreign key for table `post`
        $this->dropForeignKey(
            'fk-post_tag-post_id',
            'post_tag'
        );

        // drops index for column `post_id`
        $this->dropIndex(
            'idx-post_tag-post_id',
            'post_tag'
        );

        // drops foreign key for table `tag`
        $this->dropForeignKey(
            'fk-post_tag-tag_id',
            'post_tag'
        );

        // drops index for column `tag_id`
        $this->dropIndex(
            'idx-post_tag-tag_id',
            'post_tag'
        );

        $this->dropTable('post_tag');
    }
}
```

Начиная с версии 2.0.11, имена полей для внешних ключей промежуточной таблицы будут извлечены из объединяемых таблиц.
Тем не менее, это справедливо только в тех случаях, когда таблица имеется в базе данных, первичный ключ задан и не является составным.
В других иных случаях для поля будет сгенерировано значение по умолчанию `id`.

### Транзакции Миграций <span id="transactional-migrations"></span>

При выполнении сложных миграций баз данных, важно обеспечить каждую миграцию либо успехом, либо ошибкой, в целом так, чтобы база данных могла поддерживать целостность и непротиворечивость. Для достижения данной цели рекомендуется, заключить операции каждой миграции базы данных в [транзакции](db-dao.md#performing-transactions).

Самый простой способ реализации транзакций миграций это прописать код миграций в методы `safeUp()` и `safeDown()`. Эти два метода отличаются от методов `up()` и `down()` тем, что они неявно заключены в транзакции. В результате если какая-либо операция в этих методах не удается, все предыдущие операции будут отменены автоматически.

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

```php
<?php

use yii\db\Migration;

class m150101_185401_create_news_table extends Migration
{
    public function safeUp()
    {
        $this->createTable('news', [
            'id' => $this->primaryKey(),
            'title' => $this->string()->notNull(),
            'content' => $this->text(),
        ]);

        $this->insert('news', [
            'title' => 'test 1',
            'content' => 'content 1',
        ]);
    }

    public function safeDown()
    {
        $this->delete('news', ['id' => 1]);
        $this->dropTable('news');
    }
}
```

Обратите внимание, что обычно при выполнении нескольких операций в базе данных при помощи метода `safeUp()`, вы должны
реализовать обратный порядок исполнения в методе `safeDown()`. В приведенном выше примере мы сначала создали таблицу,
а затем вставили строку в `safeUp()`; а в `safeDown()` мы сначала удаляем строку и затем удаляем таблицу.

> Note: Не все СУБД поддерживают транзакции. И некоторые запросы к базам данных не могут быть введены в транзакции.
Для различных примеров, пожалуйста, обратитесь к [негласным обязательствам](https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html).
В этом случае вместо этих методов вы должны реализовать методы `up()` и `down()`.

### Методы доступа к базе данных <span id="db-accessing-methods"></span>

Базовый класс миграции [[yii\db\Migration]] предоставляет набор методов, которые позволяют Вам получить доступ и управлять
базами данных. Вы можете найти эти методы, их названия аналогичны [методам DAO](db-dao.md), предоставленным в классе [[yii\db\Command]].
Например, метод [[yii\db\Migration::createTable()]] позволяет создать новую таблицу, подобно методу [[yii\db\Command::createTable()]].

Преимущество методов, описанных при помощи [[yii\db\Migration]] заключается в том, что Вам не нужно явно создавать
экземпляр/копию [[yii\db\Command]] и исполнение каждого метода будет автоматически отображать полезные сообщения
говорящие вам, что операции с базой данных выполняются и сколько они идут.

Ниже представлен список всех этих методов доступа к базам данных:

* [[yii\db\Migration::execute()|execute()]]: выполнение SQL инструкции
* [[yii\db\Migration::insert()|insert()]]: вставка одной строки
* [[yii\db\Migration::batchInsert()|batchInsert()]]: вставка нескольких строк
* [[yii\db\Migration::update()|update()]]: обновление строк
* [[yii\db\Migration::delete()|delete()]]: удаление строк
* [[yii\db\Migration::createTable()|createTable()]]: создание таблицы
* [[yii\db\Migration::renameTable()|renameTable()]]: переименование таблицы
* [[yii\db\Migration::dropTable()|dropTable()]]: удаление таблицы
* [[yii\db\Migration::truncateTable()|truncateTable()]]: удаление всех строк в таблице
* [[yii\db\Migration::addColumn()|addColumn()]]: добавление столбца
* [[yii\db\Migration::renameColumn()|renameColumn()]]: переименование столбца
* [[yii\db\Migration::dropColumn()|dropColumn()]]: удаление столбца
* [[yii\db\Migration::alterColumn()|alterColumn()]]: изменения столбца
* [[yii\db\Migration::addPrimaryKey()|addPrimaryKey()]]: добавление первичного ключа
* [[yii\db\Migration::dropPrimaryKey()|dropPrimaryKey()]]: удаление первичного ключа
* [[yii\db\Migration::addForeignKey()|addForeignKey()]]: добавление внешнего ключа
* [[yii\db\Migration::dropForeignKey()|dropForeignKey()]]: удаление внешнего ключа
* [[yii\db\Migration::createIndex()|createIndex()]]: создание индекса
* [[yii\db\Migration::dropIndex()|dropIndex()]]: удаление индекса

> Info: [[yii\db\Migration]] не предоставляет методы запросов к базе данных. Это потому, что обычно не требуется отображать дополнительные сообщения об извлечении данных из базы данных. Это также, потому, что можно использовать более мощный [Построитель Запросов](db-query-builder.md) для построения и выполнения сложных запросов.

> Note: при обработке данных внутри миграции, может показаться, что использование существующих классов [Active Record](db-active-record.md), со всей их готовой бизнес логикой, будет разумным решением и упросит код миграции. Однако следует помнить, что код миграций не должен меняться, по определению. В отличие от миграций, бизнес логика приложений часто изменяется. Это может привести к нарушению работы миграции при определённых изменениях на уровне Active Record. Поэтому рекомендуется делать миграции независимыми от других частей приложения, таких как классы Active Record.


## Применение Миграций <span id="applying-migrations"></span>

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

```
yii migrate
```

Эта команда выведет список всех миграций, которые не применялись до сих пор. Если вы подтвердите, что вы хотите применить эти миграций, то этим самым запустите метод `up()` или `safeUp()` в каждом новом классе миграции, один за другим, в порядке их временного значения timestamp.

Для каждой миграции которая была успешно проведена, эта команда будет вставлять строку в таблицу базы данных с именем
`migration` записав успешное проведение миграции. Это позволяет инструменту миграции выявлять какие миграции были применены, а какие - нет.

> Note: Инструмент миграции автоматически создаст таблицу `migration` в базе данных указанной в параметре [[yii\console\controllers\MigrateController::db|db]]. По умолчанию база данных определяется как [компонент приложения](structure-application-components.md) `db`.

Иногда, необходимо применить одну или несколько новых миграций, вместо всех доступных миграций. Это возможно сделать, указав, при выполнении команды, количество миграций, которые необходимо применить. Например, следующая команда будет пытаться применить следующие три доступные миграции:

```
yii migrate 3
```

Также можно явно указать конкретную миграцию, которая должна быть применена к базе данных, это можно сделать при помощи команды `migrate/to` в одном из следующих форматов:

```
yii migrate/to 150101_185401                      # используя временную метку определяющую миграцию
yii migrate/to "2015-01-01 18:54:01"              # используя строку, которая может быть получена путем использования функции strtotime()
yii migrate/to m150101_185401_create_news_table   # используя полное имя
yii migrate/to 1392853618                         # используя временную метку UNIX
```

Если раньше имелись какие-либо не применённые миграции, до указанной конкретной миграции, то все они будут применены до данной миграции.
А если указанная миграция уже применялась ранее, то любые более поздние версии данной прикладной миграции будут отменены.

## Отмена Миграций <span id="reverting-migrations"></span>

Чтобы отменить (откатить) одну или несколько миграций, которые применялись ранее, нужно запустить следующую команду:

```
yii migrate/down     # отменяет самую последнюю применённую миграцию
yii migrate/down 3   # отменяет 3 последних применённых миграции
```

> Note: Не все миграции являются обратимыми. При попытке отката таких миграций произойдёт ошибка и остановится весь процесс отката.

## Перезагрузка Миграций <span id="redoing-migrations"></span>

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

```
yii migrate/redo        # перезагрузить последнюю применённую миграцию
yii migrate/redo 3      # перезагрузить 3 последние применённые миграции
```

> Note: Если миграция не является обратимой, вы не сможете её перезагрузить.

## Список Миграций <span id="listing-migrations"></span>

Чтобы посмотреть какие миграции были применены, а какие нет, используйте следующие команды:

```
yii migrate/history     # показать последних 10 применённых миграций
yii migrate/history 5   # показать последних 5 применённых миграций
yii migrate/history all # показать все применённые миграции

yii migrate/new         # показать первых 10 новых миграций
yii migrate/new 5       # показать первых 5 новых миграций
yii migrate/new all     # показать все новые миграции
```

## Изменение Истории Миграций <span id="modifying-migration-history"></span>

Вместо применения или отката миграций, есть возможность просто <b>отметить</b>, что база данных была обновлена до определенной миграции. Это часто используется при ручном изменении базы данных в конкретное состояние и Вам не нужно применять миграции для того, чтобы это изменение было повторно применено позже. Этой цели можно добиться с помощью следующей команды:

```
yii migrate/mark 150101_185401                      # используя временную метку определённой миграции
yii migrate/mark "2015-01-01 18:54:01"              # используя строку, которая может быть получена путем использования функции strtotime()
yii migrate/mark m150101_185401_create_news_table   # используя полное имя
yii migrate/mark 1392853618                         # используя временную метку UNIX
```

Эта команда изменит таблицу `migration` добавив или удалив определенные строки, тем самым указав, что к базе данных была применена указанная миграция. Никаких миграций не будет применяться или отменяться по этой команде.

## Настройка Миграций <span id="customizing-migrations"></span>

Есть несколько способов настроить команду миграции.

### Используя параметры командной строки<span id="using-command-line-options"></span>

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

* `interactive`: логический тип - boolean (по умолчанию `true`). Указывает, следует ли выполнять миграцию в интерактивном
  режиме. Если это значение является - `true`, то пользователю будет выдан запрос, перед выполнением командой определенных
  действий. Вы можете установить это значение в `false` если команда используется в фоновом режиме.

* `migrationPath`: строка - string (по умолчанию `@app/migrations`). Указывает каталог для хранения всех файлов классов
  миграций. Этот параметр может быть определён либо как путь до директории, либо как [псевдоним](concept-aliases.md) пути.
  Обратите внимание, что данный каталог должен существовать, иначе команда будет выдавать ошибку.

* `migrationTable`: строка - string (по умолчанию `migration`). Определяет имя таблицы в базе данных в которой хранится
  информация об истории миграций. Эта таблица будет автоматически создана командой миграции, если её не существует.
  Вы также можете создать её вручную, используя структуру `version varchar(255) primary key, apply_time integer`.

* `db`: строка - string (по умолчанию `db`). Определяет ID базы данных [компонента приложения](structure-application-components.md).
  Этот параметр представляет собой базу данных, которая подвергается миграциям при помощи команды миграций.

* `templateFile`: строка - string (по умолчанию `@yii/views/migration.php`). Указывает путь до файла шаблона, который
  используется для формирования скелета класса файлов миграции. Этот параметр может быть определён либо как путь до файла,
  либо как [псевдоним](concept-aliases.md) пути. Файл шаблона - это PHP скрипт, в котором можно использовать
  предопределенную переменную с именем `$className` для того, чтобы получить имя класса миграции.

* `generatorTemplateFiles`: массив (по умолчанию `[
        'create_table' => '@yii/views/createTableMigration.php',
        'drop_table' => '@yii/views/dropTableMigration.php',
        'add_column' => '@yii/views/addColumnMigration.php',
        'drop_column' => '@yii/views/dropColumnMigration.php',
        'create_junction' => '@yii/views/createTableMigration.php'
]`), в котором указаны файлы шаблонов для генерации миграций. Подробнее в разделе «[Генерация миграций](#generating-migrations)».

* `fields`: массив конфигураций столбцов, который используется для генерации кода миграции. По умолчанию пуст. Формат
  каждой конфигурации `ИМЯ_СТОЛБЦА:ТИП_СТОЛБЦА:ДЕКОРАТОР_СТОЛБЦА`. Например, `--fields=name:string(12):notNull` даст нам
  столбец типа строка размера 12 с ограничением `not null`.


В следующем примере показано, как можно использовать эти параметры.

Например, если мы хотим перенести модуль `forum`, чьи файлы миграций расположены в каталоге `migrations` данного модуля,
для этого мы можем использовать следующую команду:

```
# не интерактивная миграция модуля форума
yii migrate --migrationPath=@app/modules/forum/migrations --interactive=0
```

### Глобальная настройка команд <span id="configuring-command-globally"></span>

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

```php
return [
    'controllerMap' => [
        'migrate' => [
            'class' => 'yii\console\controllers\MigrateController',
            'migrationTable' => 'backend_migration',
        ],
    ],
];
```

С приведённой выше конфигурацией, каждый раз при запуске команды миграции, таблица `backend_migration` будет использована для записи истории миграций. И Вам больше не нужно указывать её через параметр `migrationTable` в командной строке.


### Миграции с пространством имен <span id="namespaced-migrations"></span>

Начиная с версии 2.0.10 вы можете использовать пространства имен при объявлении класса миграции. Вы можете указать список пространств
имен миграций через [[yii\console\controllers\MigrateController::migrationNamespaces|migrationNamespaces]]. Использование пространств
имен для классов миграции позволяет сочетать несколько источников миграций. Например:

```php
return [
    'controllerMap' => [
        'migrate' => [
            'class' => 'yii\console\controllers\MigrateController',
            'migrationNamespaces' => [
                'app\migrations', // Общие миграции приложения
                'module\migrations', // Миграции одного из модулей проекта
                'some\extension\migrations', // Миграции одного из расширений
            ],
        ],
    ],
];
```

> Замечание: миграции из различных пространств имен образуют **единую** историю, т.е. вы не сможете
  применить или откатить миграции из одного конкретного пространства имен.

Работая с миграциями по пространствам имен: при создании, отмене и т.д., следует указывать полное имя пространства имен
перед именем миграции. Имейте в виду, что символ обратного слеша (`\`), как правило, является специальным символом в консоли,
так что вам придется экранировать его соответствующим образом во избежание ошибок или неверного поведения. Например:

```
yii migrate/create 'app\\migrations\\createUserTable'
```

> Замечание: миграции заданные через [[yii\console\controllers\MigrateController::migrationPath|migrationPath]] не могут содержать
  пространство имен, миграции, объявленные с пространством имен, могут быть применены только используя свойство [[yii\console\controllers\MigrateController::migrationNamespaces]].


### Отдельностоящие Миграции <span id="separated-migrations"></span>

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

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

```php
return [
    'controllerMap' => [
        // Общие миграции приложения
        'migrate-app' => [
            'class' => 'yii\console\controllers\MigrateController',
            'migrationNamespaces' => ['app\migrations'],
            'migrationTable' => 'migration_app',
        ],
        // Миграции одного из модулей проекта
        'migrate-module' => [
            'class' => 'yii\console\controllers\MigrateController',
            'migrationNamespaces' => ['module\migrations'],
            'migrationTable' => 'migration_module',
        ],
        // Миграции одного из расширений
        'migrate-rbac' => [
            'class' => 'yii\console\controllers\MigrateController',
            'migrationPath' => '@yii/rbac/migrations',
            'migrationTable' => 'migration_rbac',
        ],
    ],
];
```

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

```
yii migrate-app
yii migrate-module
yii migrate-rbac
```


## Миграции в Несколько Баз Данных <span id="migrating-multiple-databases"></span>

По умолчанию, миграции применяются для базы данных, указанной в `db` [компоненте приложения](structure-application-components.md).
Если вы хотите применить миграцию к другой базе данных, вы можете определить параметр `db` в командной строке как показано ниже,

```
yii migrate --db=db2
```

Приведенная выше команда применит миграции к базе данных `db2`.

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

```php
<?php

use yii\db\Migration;

class m150101_185401_create_news_table extends Migration
{
    public function init()
    {
        $this->db = 'db2';
        parent::init();
    }
}
```

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

Если у вас есть несколько миграций, которые используют ту же другую базу данных, то рекомендуется создать базовый класс миграций выше кода `init()`. Затем каждый класс миграции может расширяться от этого базового класса.

> Совет: Кроме установки свойства [[yii\db\Migration::db|db]], вы также можете работать с разными базами данных путем создания нового соединения с конкретной базой данных в классе Вашей миграции. Можно использовать [DAO методы](db-dao.md) с этими соединениями для манипулирования различными базами данных.

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

```
yii migrate --migrationPath=@app/migrations/db1 --db=db1
yii migrate --migrationPath=@app/migrations/db2 --db=db2
...
```

Первая команда применит миграции в директории `@app/migrations/db1` к базе данных `db1`, а вторая команда применит миграции в директории `@app/migrations/db2` к базе данных `db2` и так далее.
