Maison >développement back-end >tutoriel php >Yii 的修行之路(一)@Migration 数据迁移
数据迁移就是数据库表在团队建的迁移操作,达到团队相互间的信息同步,数据统一。
一般步骤:
1、在 yii2 的 migrate 中,通常用来对数据库数据表进行修改操作,主要对结构和小部分数据进行操作(很少会遇到大数据,如果是面对数据量比较大的情况,采用数据表的直接导出导入)。
2、本地生成或修改数据库表,后端执行语句: ./yii migrate/create
3、后端执行 migrate 指令后会生成一个 migrate 脚本,这个脚本里面主要用来存放 SQL语句,也会随着代码发布而上传,以供其他成员同步数据库,实现真正的数据迁移。
4、其他成员拉去最新代码回本地后,执行 ./yii migrate 更新数据迁移状态,把最新的数据迁移同步到本地。
在开发和维护一个数据库驱动的应用程序时,数据库的结构会随代码的改变而改变。
例如,在开发应用程序的过程中,会增加一张新表且必须得加进来; 在应用程序被部署到生产环境后,需要建立一个索引来提高查询的性能等等。 因为一个数据库结构发生改变的时候源代码也经常会需要做出改变,Yii 提供了一个 数据库迁移 功能,该功能可以记录数据库的变化, 以便使数据库和源代码一起受版本控制。
如下的步骤向我们展示了数据库迁移工具是如何为开发团队所使用的:
Tim 创建了一个新的迁移对象(例如,创建一张新的表单,改变字段的定义等)。
Tim 将这个新的迁移对象提交到代码管理系统(例如,Git,Mercurial)。
Doug 从代码管理系统当中更新版本并获取到这个新的迁移对象。
Doug 把这个迁移对象提交到本地的开发数据库当中,这样一来,Doug 同步了 Tim 所做的修改。
如下的步骤向我们展示了如何发布一个附带数据库迁移的新版本到生产环境当中:
Scott 为一个包含数据库迁移的项目版本创建了一个发布标签。
Scott 把发布标签的源代码更新到生产环境的服务器上。
Scott 把所有的增量数据库迁移提交到生产环境数据库当中。
Yii 提供了一整套的迁移命令行工具,通过这些工具你可以:
创建新的迁移(./yii migrate/create 迁移描述);
提交迁移;
恢复迁移;
重新提交迁移;
现实迁移历史和状态。
所有的这些工具都可以通过 yii migrate 命令来进行操作。注意:迁移不仅仅只作用于数据库表,它同样会调整现有的数据来适应新的表单、创建 RBAC 分层、又或者是清除缓存。
使用如下命令来创建一个新的迁移:
yii migrate/create <name>
必填参数 name 的作用是对新的迁移做一个简要的描述。
例如,如果这个迁移是用来创建一个叫做 news 的表单的,那么你可以使用create_news_table 这个名称并运行如下命令:
yii migrate/create create_news_table
注意:因为 name 参数会被用来生成迁移的类名的一部分,所以该参数应当只包含字母、数字和下划线。
如上命令将会在 @app/migrations 目录下创建一个新的名为 m150101_185401_create_news_table.php 的 PHP 类文件。
该文件包含如下的代码,它们用来声明一个迁移类 m150101_185401_create_news_table,并附有代码框架:
<?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; } }
每个数据库迁移都会被定义为一个继承自 yiidbMigration 的 PHP 类。类的名称按照 m
在迁移类当中,你应当在 up() 方法中编写改变数据库结构的代码。你可能还需要在 down() 方法中编写代码来恢复由 up() 方法所做的改变。
当你通过 migration 升级数据库时, up() 方法将会被调用,反之, down() 将会被调用。如下代码展示了如何通过迁移类来创建一张 news 表:
use yii\db\Schema; use yii\db\Migration; class m150101_185401_create_news_table extends \yii\db\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'); } }
注意:并不是所有迁移都是可恢复的。
例如,如果 up() 方法删除了表中的一行数据,这将无法通过 down() 方法来恢复这条数据。有时候,你也许只是懒得去执行 down() 方法了,因为它在恢复数据库迁移方面并不是那么的通用。在这种情况下,你应当在 down() 方法中返回 false 来表明这个 migration 是无法恢复的。
为了将数据库升级到最新的结构,你应该使用如下命令来提交所有新的迁移:
yii migrate
这条命令会列出迄今为止所有未提交的迁移。
如果你确定你需要提交这些迁移,它将会按照类名当中的时间戳的顺序,一个接着一个的运行每个新的迁移类里面的 up() 或者是 safeUp() 方法。如果其中任意一个迁移提交失败了,那么这条命令将会退出并停止剩下的那些还未执行的迁移。
对于每一个成功提交的迁移,这条命令都会在一个叫做 migration 的数据库表中插入一条包含应用程序成功提交迁移的记录,该记录将帮助迁移工具判断哪些迁移已经提交, 哪些还没有提交。
提示:迁移工具将会自动在数据库当中创建 migration 表,该数据库是在该命令的 yiiconsolecontrollersMigrateController::db 选项当中指定的。默认情况下,是由 db application component 指定的。
有时,你可能只需要提交一个或者少数的几个迁移,你可以使用该命令指定需要执行的条数,而不是执行所有的可用迁移。例如,如下命令将会尝试提交前三个可用的迁移:
yii migrate 3
你也可以指定一个特定的迁移,按照如下格式使用 migrate/to 命令来指定数据库应该提交哪一个迁移:
yii migrate/to 150101_185401 # using timestamp to specify the migration 使用时间戳来指定迁移 yii migrate/to "2015-01-01 18:54:01" # using a string that can be parsed by strtotime() 使用一个可以被 strtotime() 解析的字符串 yii migrate/to m150101_185401_create_news_table # using full name 使用全名 yii migrate/to 1392853618 # using UNIX timestamp 使用 UNIX 时间戳
如果在指定要提交的迁移前面还有未提交的迁移,那么在执行这个被指定的迁移之前,这些还未提交的迁移会先被提交。
如果被指定提交的迁移在之前已经被提交过,那么在其之后的那些迁移将会被还原。
你可以使用如下命令来还原其中一个或多个意见被提交过的迁移:
yii migrate/down # revert the most recently applied migration 还原最近一次提交的迁移 yii migrate/down 3 # revert the most 3 recently applied migrations 还原最近三次提交的迁移
注意:并不是所有的迁移都能被还原。尝试还原这类迁移将可能导致报错甚至是终止所有的还原进程。
重做迁移的意思是先还原指定的迁移,然后再次提交。如下所示:
yii migrate/redo # redo the last applied migration 重做最近一次提交的迁移 yii migrate/redo 3 # redo the last 3 applied migrations 重做最近三次提交的迁移
注意:如果一个迁移是不能被还原的,那么你将无法对它进行重做。
你可以使用如下命令列出那些提交了的或者是还未提交的迁移:
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 # 显示所有还未提交的迁移
有时候你也许需要简单的标记一下你的数据库已经升级到一个特定的迁移,而不是实际提交或者是还原迁移。这个经常会发生在你手动的改变数据库的一个特定状态,而又不想相应的迁移被重复提交。那么你可以使用如下命令来达到目的:
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 表当中的某几行数据来表明数据库已经提交到了指定的某个迁移上。
执行这条命令期间不会有任何的迁移会被提交或还原。
在运行迁移命令的时候每次都要重复的输入一些同样的参数会很烦人,这时候,你可以选择在应用程序配置当中进行全局配置,一劳永逸:
return [ 'controllerMap' => [ 'migrate' => [ 'class' => 'yii\console\controllers\MigrateController', 'migrationTable' => 'backend_migration', ], ],];
如上所示配置,在每次运行迁移命令的时候,backend_migration 表将会被用来记录迁移历史。你再也不需要通过migrationTable 命令行参数来指定这张历史纪录表了。
默认情况下,迁移将会提交到由 db application component 所定义的同一个数据库当中。如果你需要提交到不同的数据库,你可以像下面那样指定 db 命令行选项,
yii migrate --db=db2
上面的命令将会把迁移提交到 db2 数据库当中。
偶尔有限时候你需要提交 一些 迁移到一个数据库,而另外一些则提交到另一个数据库。为了达到这个目的,你应该在实现一个迁移类的时候指定需要用到的数据库组件的 ID , 如下所示:
use yii\db\Schema;use yii\db\Migration;class m150101_185401_create_news_table extends Migration{ public function init() { $this->db = 'db2'; parent::init(); }}
即使你使用 db 命令行选项指定了另外一个不同的数据库,上面的迁移还是会被提交到 db2 当中。需要注意的是这个时候迁移的历史信息依然会被记录到 db 命令行选项所指定的数据库当中。
如果有多个迁移都使用到了同一个数据库,那么建议你创建一个迁移的基类,里面包含上述的 init() 代码。然后每个迁移类都继承这个基类就可以了。
提示:除了在 yiidbMigration::db 参数当中进行设置以外,你还可以通过在迁移类中创建新的数据库连接来操作不同的数据库。然后通过这些连接再使用 DAO 方法 来操作不同的数据库。
另外一个可以让你迁移多个数据库的策略是把迁移存放到不同的目录下,然后你可以通过如下命令分别对不同的数据库进行迁移:
yii migrate --migrationPath=@app/migrations/db1 --db=db1yii migrate --migrationPath=@app/migrations/db2 --db=db2...
第一条命令将会把 @app/migrations/db1 目录下的迁移提交到 db1 数据库当中,第二条命令则会把 @app/migrations/db2 下的迁移提交到 db2 数据库当中,以此类推。