|
|
|
@@ -2,9 +2,9 @@ Database Migration
|
|
|
|
|
==================
|
|
|
|
|
|
|
|
|
|
During the course of developing and maintaining a database-driven application, the structure of the database
|
|
|
|
|
being used evolves just like the source code does. For example, during the development of an application,
|
|
|
|
|
being used evolves just like the source code does. For example, during the development of an application,
|
|
|
|
|
a new table may be found necessary; after the application is deployed to production, it may be discovered
|
|
|
|
|
that an index should be created to improve the query performance; and so on. Because a database structure change
|
|
|
|
|
that an index should be created to improve the query performance; and so on. Because a database structure change
|
|
|
|
|
often requires some source code changes, Yii supports the so-called *database migration* feature that allows
|
|
|
|
|
you to keep track of database changes in terms of *database migrations* which are version-controlled together
|
|
|
|
|
with the source code.
|
|
|
|
@@ -14,7 +14,7 @@ The following steps show how database migration can be used by a team during dev
|
|
|
|
|
1. Tim creates a new migration (e.g. creates a new table, changes a column definition, etc.).
|
|
|
|
|
2. Tim commits the new migration into the source control system (e.g. Git, Mercurial).
|
|
|
|
|
3. Doug updates his repository from the source control system and receives the new migration.
|
|
|
|
|
4. Doug applies the migration to his local development database, thereby synchronizing his database
|
|
|
|
|
4. Doug applies the migration to his local development database, thereby synchronizing his database
|
|
|
|
|
to reflect the changes that Tim has made.
|
|
|
|
|
|
|
|
|
|
And the following steps show how to deploy a new release with database migrations to production:
|
|
|
|
@@ -47,7 +47,7 @@ To create a new migration, run the following command:
|
|
|
|
|
yii migrate/create <name>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The required `name` argument gives a brief description about the new migration. For example, if
|
|
|
|
|
The required `name` argument gives a brief description about the new migration. For example, if
|
|
|
|
|
the migration is about creating a new table named *news*, you may use the name `create_news_table`
|
|
|
|
|
and run the following command:
|
|
|
|
|
|
|
|
|
@@ -65,20 +65,32 @@ a migration class `m150101_185401_create_news_table` with the skeleton code:
|
|
|
|
|
```php
|
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
use yii\db\Schema;
|
|
|
|
|
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()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
@@ -91,7 +103,7 @@ class name is automatically generated in the format of `m<YYMMDD_HHMMSS>_<Name>`
|
|
|
|
|
In the migration class, you are expected to write code in the `up()` method that makes changes to the database structure.
|
|
|
|
|
You may also want to write code in the `down()` method to revert the changes made by `up()`. The `up()` method is invoked
|
|
|
|
|
when you upgrade the database with this migration, while the `down()` method is invoked when you downgrade the database.
|
|
|
|
|
The following code shows how you may implement the migration class to create a `news` table:
|
|
|
|
|
The following code shows how you may implement the migration class to create a `news` table:
|
|
|
|
|
|
|
|
|
|
```php
|
|
|
|
|
<?php
|
|
|
|
@@ -114,17 +126,16 @@ class m150101_185401_create_news_table extends Migration
|
|
|
|
|
{
|
|
|
|
|
$this->dropTable('news');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
> Info: Not all migrations are reversible. For example, if the `up()` method deletes a row of a table, you may
|
|
|
|
|
not be able to recover this row in the `down()` method. Sometimes, you may be just too lazy to implement
|
|
|
|
|
not be able to recover this row in the `down()` method. Sometimes, you may be just too lazy to implement
|
|
|
|
|
the `down()`, because it is not very common to revert database migrations. In this case, you should return
|
|
|
|
|
`false` in the `down()` method to indicate that the migration is not reversible.
|
|
|
|
|
|
|
|
|
|
The base migration class [[yii\db\Migration]] exposes a database connection via the [[yii\db\Migration::db|db]]
|
|
|
|
|
property. You can use it to manipulate the database schema using the methods as described in
|
|
|
|
|
property. You can use it to manipulate the database schema using the methods as described in
|
|
|
|
|
[Working with Database Schema](db-dao.md#working-with-database-schema-).
|
|
|
|
|
|
|
|
|
|
Rather than using physical types, when creating a table or column you should use *abstract types*
|
|
|
|
@@ -138,16 +149,15 @@ into `int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY`, while `TYPE_STRING` becomes
|
|
|
|
|
You can append additional constraints when using abstract types. In the above example, ` NOT NULL` is appended
|
|
|
|
|
to `Schema::TYPE_STRING` to specify that the column cannot be null.
|
|
|
|
|
|
|
|
|
|
> Info: The mapping between abstract types and physical types is specified by
|
|
|
|
|
> Info: The mapping between abstract types and physical types is specified by
|
|
|
|
|
the [[yii\db\QueryBuilder::$typeMap|$typeMap]] property in each concrete `QueryBuilder` class.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Since version 2.0.6 schema builder which provides more convenient way defining column schema was introduced so migration above
|
|
|
|
|
could be written like the following:
|
|
|
|
|
|
|
|
|
|
```php
|
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
use yii\db\Schema;
|
|
|
|
|
use yii\db\Migration;
|
|
|
|
|
|
|
|
|
|
class m150101_185401_create_news_table extends Migration
|
|
|
|
@@ -165,7 +175,6 @@ class m150101_185401_create_news_table extends Migration
|
|
|
|
|
{
|
|
|
|
|
$this->dropTable('news');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
@@ -175,18 +184,18 @@ A list of all available methods for defining the column types is available in th
|
|
|
|
|
### Transactional Migrations <span id="transactional-migrations"></span>
|
|
|
|
|
|
|
|
|
|
While performing complex DB migrations, it is important to ensure each migration to either succeed or fail as a whole
|
|
|
|
|
so that the database can maintain integrity and consistency. To achieve this goal, it is recommended that you
|
|
|
|
|
so that the database can maintain integrity and consistency. To achieve this goal, it is recommended that you
|
|
|
|
|
enclose the DB operations of each migration in a [transaction](db-dao.md#performing-transactions-).
|
|
|
|
|
|
|
|
|
|
An even easier way of implementing transactional migrations is to put migration code in the `safeUp()` and `safeDown()`
|
|
|
|
|
|
|
|
|
|
An even easier way of implementing transactional migrations is to put migration code in the `safeUp()` and `safeDown()`
|
|
|
|
|
methods. These two methods differ from `up()` and `down()` in that they are enclosed implicitly in a transaction.
|
|
|
|
|
As a result, if any operation in these methods fails, all prior operations will be rolled back automatically.
|
|
|
|
|
|
|
|
|
|
In the following example, besides creating the `news` table we also insert an initial row into this table.
|
|
|
|
|
|
|
|
|
|
```php
|
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
use yii\db\Schema;
|
|
|
|
|
use yii\db\Migration;
|
|
|
|
|
|
|
|
|
|
class m150101_185401_create_news_table extends Migration
|
|
|
|
@@ -198,7 +207,7 @@ class m150101_185401_create_news_table extends Migration
|
|
|
|
|
'title' => $this->string()->notNull(),
|
|
|
|
|
'content' => $this->text(),
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$this->insert('news', [
|
|
|
|
|
'title' => 'test 1',
|
|
|
|
|
'content' => 'content 1',
|
|
|
|
@@ -213,7 +222,7 @@ class m150101_185401_create_news_table extends Migration
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Note that usually when you perform multiple DB operations in `safeUp()`, you should reverse their execution order
|
|
|
|
|
Note that usually when you perform multiple DB operations in `safeUp()`, you should reverse their execution order
|
|
|
|
|
in `safeDown()`. In the above example we first create the table and then insert a row in `safeUp()`; while
|
|
|
|
|
in `safeDown()` we first delete the row and then drop the table.
|
|
|
|
|
|
|
|
|
@@ -225,12 +234,12 @@ in `safeDown()` we first delete the row and then drop the table.
|
|
|
|
|
### Database Accessing Methods <span id="db-accessing-methods"></span>
|
|
|
|
|
|
|
|
|
|
The base migration class [[yii\db\Migration]] provides a set of methods to let you access and manipulate databases.
|
|
|
|
|
You may find these methods are named similarly as the [DAO methods](db-dao.md) provided by the [[yii\db\Command]] class.
|
|
|
|
|
For example, the [[yii\db\Migration::createTable()]] method allows you to create a new table,
|
|
|
|
|
just like [[yii\db\Command::createTable()]] does.
|
|
|
|
|
You may find these methods are named similarly as the [DAO methods](db-dao.md) provided by the [[yii\db\Command]] class.
|
|
|
|
|
For example, the [[yii\db\Migration::createTable()]] method allows you to create a new table,
|
|
|
|
|
just like [[yii\db\Command::createTable()]] does.
|
|
|
|
|
|
|
|
|
|
The benefit of using the methods provided by [[yii\db\Migration]] is that you do not need to explicitly
|
|
|
|
|
create [[yii\db\Command]] instances and the execution of each method will automatically display useful messages
|
|
|
|
|
The benefit of using the methods provided by [[yii\db\Migration]] is that you do not need to explicitly
|
|
|
|
|
create [[yii\db\Command]] instances and the execution of each method will automatically display useful messages
|
|
|
|
|
telling you what database operations are done and how long they take.
|
|
|
|
|
|
|
|
|
|
Below is the list of all these database accessing methods:
|
|
|
|
@@ -276,18 +285,18 @@ yii migrate
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
This command will list all migrations that have not been applied so far. If you confirm that you want to apply
|
|
|
|
|
these migrations, it will run the `up()` or `safeUp()` method in every new migration class, one after another,
|
|
|
|
|
these migrations, it will run the `up()` or `safeUp()` method in every new migration class, one after another,
|
|
|
|
|
in the order of their timestamp values. If any of the migrations fails, the command will quit without applying
|
|
|
|
|
the rest of the migrations.
|
|
|
|
|
|
|
|
|
|
For each migration that has been successfully applied, the command will insert a row into a database table named
|
|
|
|
|
For each migration that has been successfully applied, the command will insert a row into a database table named
|
|
|
|
|
`migration` to record the successful application of the migration. This will allow the migration tool to identify
|
|
|
|
|
which migrations have been applied and which have not.
|
|
|
|
|
|
|
|
|
|
> Info: The migration tool will automatically create the `migration` table in the database specified by
|
|
|
|
|
the [[yii\console\controllers\MigrateController::db|db]] option of the command. By default, the database
|
|
|
|
|
is specified by the `db` [application component](structure-application-components.md).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Sometimes, you may only want to apply one or a few new migrations, instead of all available migrations.
|
|
|
|
|
You can do so by specifying the number of migrations that you want to apply when running the command.
|
|
|
|
|
For example, the following command will try to apply the next three available migrations:
|
|
|
|
@@ -331,7 +340,7 @@ Redoing migrations means first reverting the specified migrations and then apply
|
|
|
|
|
as follows:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
yii migrate/redo # redo the last applied migration
|
|
|
|
|
yii migrate/redo # redo the last applied migration
|
|
|
|
|
yii migrate/redo 3 # redo the last 3 applied migrations
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
@@ -380,12 +389,12 @@ There are several ways to customize the migration command.
|
|
|
|
|
|
|
|
|
|
The migration command comes with a few command-line options that can be used to customize its behaviors:
|
|
|
|
|
|
|
|
|
|
* `interactive`: boolean (defaults to true), specifies whether to perform migrations in an interactive mode.
|
|
|
|
|
* `interactive`: boolean (defaults to true), specifies whether to perform migrations in an interactive mode.
|
|
|
|
|
When this is true, the user will be prompted before the command performs certain actions.
|
|
|
|
|
You may want to set this to false if the command is being used in a background process.
|
|
|
|
|
|
|
|
|
|
* `migrationPath`: string (defaults to `@app/migrations`), specifies the directory storing all migration
|
|
|
|
|
class files. This can be specified as either a directory path or a path [alias](concept-aliases.md).
|
|
|
|
|
* `migrationPath`: string (defaults to `@app/migrations`), specifies the directory storing all migration
|
|
|
|
|
class files. This can be specified as either a directory path or a path [alias](concept-aliases.md).
|
|
|
|
|
Note that the directory must exist, or the command may trigger an error.
|
|
|
|
|
|
|
|
|
|
* `migrationTable`: string (defaults to `migration`), specifies the name of the database table for storing
|
|
|
|
@@ -449,7 +458,8 @@ database. To achieve this goal, when implementing a migration class you should e
|
|
|
|
|
ID that the migration would use, like the following:
|
|
|
|
|
|
|
|
|
|
```php
|
|
|
|
|
use yii\db\Schema;
|
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
use yii\db\Migration;
|
|
|
|
|
|
|
|
|
|
class m150101_185401_create_news_table extends Migration
|
|
|
|
|