yii2.0数据库迁移教程【多个数据库同时同步数据】
本文讲述了yii2.0数据库迁移的方法。分享给大家供大家参考,具体如下:
创建迁移
使用如下命令来创建一个新的迁移:
yiimigrate/create<name>
必填参数name的作用是对新的迁移做一个简要的描述。例如,如果这个迁移是用来往多个数据库同一张表 (假设每个数据库都有news表) 添加字段的,那么你可以使用addColumn_news(该名称自定义)这个名称并运行如下命令:
yiimigrate/createaddColumn_news
注意:因为name参数会被用来生成迁移的类名的一部分,所以该参数应当只包含字母、数字和下划线。
如上命令将会在@app/migrations目录下创建一个新的名为m150101_185401_addColumn_news.php的PHP类文件。该文件包含如下的代码,它们用来声明一个迁移类m150101_185401_addColumn_news,并附有代码框架:
<?php useyii\db\Schema; useyii\db\Migration; classm150101_185401_addColumn_newsextendsMigration { //createDbs该方法是获取数据库对象返回 privatefunctioncreateDbs(){ $dbs=[]; $dbs_info=\Yii::$app->params['db']; foreach($dbs_infoas$k=>$v){ $dbs[$k]=\Yii::createObject($v); } return$dbs; } //up()该方法是往不同的数据库的news表添加name,nickname,age,sex,site_id等字段 publicfunctionup() { $dbs=$this->createDbs(); foreach($dbsas$v){//《------遍历讲字段同时添加到不同的数据库中 $this->db=$v; $this->addColumn('{{%news}}','name','varchar(20)'); $this->addColumn('{{%news}}','nickname','varchar(20)'); $this->addColumn('{{%news}}','age','int(3)'); $this->addColumn('{{%news}}','sex','int(1)'); $this->addColumn('{{%news}}','site_id','int(5)'); } } //down()该方法与up()方法相反,是删除字段的意思 publicfunctiondown() { $dbs=$this->createDbs(); foreach($dbsas$v){ $this->db=$v; $this->dropColumn('{{%news}}','name','varchar(20)'); $this->dropColumn('{{%news}}','nickname','varchar(20)'); $this->dropColumn('{{%news}}','age','int(3)'); $this->dropColumn('{{%news}}','sex','int(1)'); $this->dropColumn('{{%news}}','site_id','int(5)'); } } }
每个数据库迁移都会被定义为一个继承自yii\db\Migration的PHP类。类的名称按照m<YYMMDD_HHMMSS>_<Name>的格式自动生成,其中
<YYMMDD_HHMMSS>指执行创建迁移命令的UTC时间。
<Name>和你执行命令时所带的name参数值相同。
在迁移类当中,你应当在up()方法中编写改变数据库结构的代码。你可能还需要在down()方法中编写代码来恢复由up()方法所做的改变。当你通过migration升级数据库时,up()方法将会被调用,反之,down()将会被调用。如下代码展示了如何通过迁移类来创建一张news表:
useyii\db\Schema; useyii\db\Migration; classm150101_185401_create_news_tableextends\yii\db\Migration { publicfunctionup() { $this->createTable('news',[ 'id'=>Schema::TYPE_PK, 'title'=>Schema::TYPE_STRING.'NOTNULL', 'content'=>Schema::TYPE_TEXT, ]); } publicfunctiondown() { $this->dropTable('news'); } }
注意:并不是所有迁移都是可恢复的。例如,如果up()方法删除了表中的一行数据,这将无法通过down()方法来恢复这条数据。有时候,你也许只是懒得去执行down()方法了,因为它在恢复数据库迁移方面并不是那么的通用。在这种情况下,你应当在down()方法中返回false来表明这个migration是无法恢复的。
访问数据库的方法
迁移的基类yii\db\Migration提供了一整套访问和操作数据库的方法。你可能会发现这些方法的命名和yii\db\Command类提供的DAO方法很类似。例如,yii\db\Migration::createTable()方法可以创建一张新的表,这和yii\db\Command::createTable()的功能是一模一样的。
使用yii\db\Migration所提供的方法的好处在于你不需要再显式的创建yii\db\Command实例,而且在执行每个方法的时候都会显示一些有用的信息来告诉我们数据库操作是不是都已经完成,还有它们完成这些操作花了多长时间等等。
如下是所有这些数据库访问方法的列表:
yii\db\Migration::execute():执行一条SQL语句
yii\db\Migration::insert():插入单行数据
yii\db\Migration::batchInsert():插入多行数据
yii\db\Migration::update():更新数据
yii\db\Migration::delete():删除数据
yii\db\Migration::createTable():创建表
yii\db\Migration::renameTable():重命名表名
yii\db\Migration::dropTable():删除一张表
yii\db\Migration::truncateTable():清空表中的所有数据
yii\db\Migration::addColumn():加一个字段
yii\db\Migration::renameColumn():重命名字段名称
yii\db\Migration::dropColumn():删除一个字段
yii\db\Migration::alterColumn():修改字段
yii\db\Migration::addPrimaryKey():添加一个主键
yii\db\Migration::dropPrimaryKey():删除一个主键
yii\db\Migration::addForeignKey():添加一个外键
yii\db\Migration::dropForeignKey():删除一个外键
yii\db\Migration::createIndex():创建一个索引
yii\db\Migration::dropIndex():删除一个索引
提交迁移
为了将数据库升级到最新的结构,你应该使用如下命令来提交所有新的迁移:
yiimigrate
这条命令会列出迄今为止所有未提交的迁移。如果你确定你需要提交这些迁移,它将会按照类名当中的时间戳的顺序,一个接着一个的运行每个新的迁移类里面的up()或者是safeUp()方法。如果其中任意一个迁移提交失败了,那么这条命令将会退出并停止剩下的那些还未执行的迁移。
对于每一个成功提交的迁移,这条命令都会在一个叫做migration的数据库表中插入一条包含应用程序成功提交迁移的记录,该记录将帮助迁移工具判断哪些迁移已经提交,哪些还没有提交。
提示:迁移工具将会自动在数据库当中创建migration表,该数据库是在该命令的yii\console\controllers\MigrateController::db选项当中指定的。默认情况下,是由dbapplicationcomponent指定的。
有时,你可能只需要提交一个或者少数的几个迁移,你可以使用该命令指定需要执行的条数,而不是执行所有的可用迁移。例如,如下命令将会尝试提交前三个可用的迁移:
yiimigrate3
你也可以指定一个特定的迁移,按照如下格式使用migrate/to命令来指定数据库应该提交哪一个迁移:
yiimigrate/to150101_185401#usingtimestamptospecifythemigration使用时间戳来指定迁移 yiimigrate/to"2015-01-0118:54:01"#usingastringthatcanbeparsedbystrtotime()使用一个可以被strtotime()解析的字符串 yiimigrate/tom150101_185401_create_news_table#usingfullname使用全名 yiimigrate/to1392853618#usingUNIXtimestamp使用UNIX时间戳
如果在指定要提交的迁移前面还有未提交的迁移,那么在执行这个被指定的迁移之前,这些还未提交的迁移会先被提交。
如果被指定提交的迁移在之前已经被提交过,那么在其之后的那些迁移将会被还原。
还原迁移
你可以使用如下命令来还原其中一个或多个意见被提交过的迁移:
yiimigrate/down#revertthemostrecentlyappliedmigration还原最近一次提交的迁移 yiimigrate/down3#revertthemost3recentlyappliedmigrations还原最近三次提交的迁移
注意:并不是所有的迁移都能被还原。尝试还原这类迁移将可能导致报错甚至是终止所有的还原进程。
重做迁移
重做迁移的意思是先还原指定的迁移,然后再次提交。如下所示:
yiimigrate/redo#redothelastappliedmigration重做最近一次提交的迁移 yiimigrate/redo3#redothelast3appliedmigrations重做最近三次提交的迁移
注意:如果一个迁移是不能被还原的,那么你将无法对它进行重做。
列出迁移
你可以使用如下命令列出那些提交了的或者是还未提交的迁移:
yiimigrate/history#显示最近10次提交的迁移 yiimigrate/history5#显示最近5次提交的迁移 yiimigrate/historyall#显示所有已经提交过的迁移 yiimigrate/new#显示前10个还未提交的迁移 yiimigrate/new5#显示前5个还未提交的迁移 yiimigrate/newall#显示所有还未提交的迁移
修改迁移历史
有时候你也许需要简单的标记一下你的数据库已经升级到一个特定的迁移,而不是实际提交或者是还原迁移。这个经常会发生在你手动的改变数据库的一个特定状态,而又不想相应的迁移被重复提交。那么你可以使用如下命令来达到目的:
yiimigrate/mark150101_185401#使用时间戳来指定迁移 yiimigrate/mark"2015-01-0118:54:01"#使用一个可以被strtotime()解析的字符串 yiimigrate/markm150101_185401_create_news_table#使用全名 yiimigrate/mark1392853618#使用UNIX时间戳
该命令将会添加或者删除migration表当中的某几行数据来表明数据库已经提交到了指定的某个迁移上。执行这条命令期间不会有任何的迁移会被提交或还原。
自定义迁移
有很多方法可以自定义迁移命令。
使用命令行选项
迁移命令附带了几个命令行选项,可以用来自定义它的行为:
interactive:boolean(默认值为true),指定是否以交互模式来运行迁移。当被设置为true时,在命令执行某些操作前,会提示用户。如果你希望在后台执行该命令,那么你应该把它设置成false。
migrationPath:string(默认值为@app/migrations),指定存放所有迁移类文件的目录。该选项可以是一个目录的路径,也可以是路径别名。需要注意的是指定的目录必选存在,否则将会触发一个错误。
migrationTable:string(默认值为migration),指定用于存储迁移历史信息的数据库表名称。如果这张表不存在,那么迁移命令将自动创建这张表。当然你也可以使用这样的字段结构:version
varchar(255)primarykey,apply_timeinteger来手动创建这张表。
db:string(默认值为db),指定数据库applicationcomponent的ID。它指的是将会被该命令迁移的数据库。
templateFile:string(defaultsto@yii/views/migration.php),指定生产迁移框架代码类文件的模版文件路径。该选项即可以使用文件路径来指定,也可以使用路径别名来指定。该模版文件是一个可以使用预定义变量$className来获取迁移类名称的PHP脚本。
如下例子向我们展示了如何使用这些选项:
例如,如果我们需要迁移一个forum模块,而该迁移文件放在该模块下的migrations目录当中,那么我们可以使用如下命令:
#在forum模块中以非交互模式进行迁移 yiimigrate--migrationPath=@app/modules/forum/migrations--interactive=0
全局配置命令
在运行迁移命令的时候每次都要重复的输入一些同样的参数会很烦人,这时候,你可以选择在应用程序配置当中进行全局配置,一劳永逸:
return[ 'controllerMap'=>[ 'migrate'=>[ 'class'=>'yii\console\controllers\MigrateController', 'migrationTable'=>'backend_migration', ], ], ];
如上所示配置,在每次运行迁移命令的时候,backend_migration表将会被用来记录迁移历史。你再也不需要通过migrationTable命令行参数来指定这张历史纪录表了。
迁移多个数据库
默认情况下,迁移将会提交到由dbapplicationcomponent所定义的同一个数据库当中。如果你需要提交到不同的数据库,你可以像下面那样指定db命令行选项,
yiimigrate--db=db2
上面的命令将会把迁移提交到db2数据库当中。
偶尔有限时候你需要提交一些迁移到一个数据库,而另外一些则提交到另一个数据库。为了达到这个目的,你应该在实现一个迁移类的时候指定需要用到的数据库组件的ID,如下所示:
useyii\db\Schema; useyii\db\Migration; classm150101_185401_create_news_tableextendsMigration { publicfunctioninit() { $this->db='db2'; parent::init(); } }
即使你使用db命令行选项指定了另外一个不同的数据库,上面的迁移还是会被提交到db2当中。需要注意的是这个时候迁移的历史信息依然会被记录到db命令行选项所指定的数据库当中。
如果有多个迁移都使用到了同一个数据库,那么建议你创建一个迁移的基类,里面包含上述的init()代码。然后每个迁移类都继承这个基类就可以了。
提示:除了在yii\db\Migration::db参数当中进行设置以外,你还可以通过在迁移类中创建新的数据库连接来操作不同的数据库。然后通过这些连接再使用DAO方法来操作不同的数据库。
另外一个可以让你迁移多个数据库的策略是把迁移存放到不同的目录下,然后你可以通过如下命令分别对不同的数据库进行迁移:
yiimigrate--migrationPath=@app/migrations/db1--db=db1 yiimigrate--migrationPath=@app/migrations/db2--db=db2 ...
第一条命令将会把@app/migrations/db1目录下的迁移提交到db1数据库当中,第二条命令则会把@app/migrations/db2下的迁移提交到db2数据库当中,以此类推。
更多关于Yii相关内容感兴趣的读者可查看本站专题:《Yii框架入门及常用技巧总结》、《php优秀开发框架总结》、《smarty模板入门基础教程》、《php面向对象程序设计入门教程》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》
希望本文所述对大家基于Yii框架的PHP程序设计有所帮助。