yii2.0数据库迁移教程【多个数据库同时同步数据】


Posted in PHP onOctober 08, 2016

本文讲述了yii2.0数据库迁移的方法。分享给大家供大家参考,具体如下:

创建迁移

使用如下命令来创建一个新的迁移:

yii migrate/create <name>

必填参数 name 的作用是对新的迁移做一个简要的描述。例如,如果这个迁移是用来往多个数据库同一张表  ( 假设每个数据库都有news表 )   添加字段的,那么你可以使用addColumn_news (该名称自定义)这个名称并运行如下命令:

yii migrate/create addColumn_news

注意:因为 name 参数会被用来生成迁移的类名的一部分,所以该参数应当只包含字母、数字和下划线。

如上命令将会在 @app/migrations 目录下创建一个新的名为 m150101_185401_addColumn_news.php 的 PHP 类文件。该文件包含如下的代码,它们用来声明一个迁移类 m150101_185401_addColumn_news,并附有代码框架:

<?php
use yii\db\Schema;
use yii\db\Migration;
class m150101_185401_addColumn_news extends Migration
{
//createDbs 该方法是获取数据库对象返回
private function createDbs(){
  $dbs = [];
  $dbs_info =\Yii::$app->params['db'];
  foreach($dbs_info as $k=>$v){
    $dbs[$k] = \Yii::createObject($v);
  }
  return $dbs;
}
//up() 该方法是往不同的数据库的news表添加 name,nickname,age,sex,site_id等字段
public function up()
{
  $dbs = $this->createDbs();
  foreach($dbs as $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()方法相反,是删除字段的意思
public function down()
{
  $dbs = $this->createDbs();
  foreach($dbs as $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 表:

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\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(): 删除一个索引

提交迁移

为了将数据库升级到最新的结构,你应该使用如下命令来提交所有新的迁移:

yii migrate

这条命令会列出迄今为止所有未提交的迁移。如果你确定你需要提交这些迁移,它将会按照类名当中的时间戳的顺序,一个接着一个的运行每个新的迁移类里面的 up() 或者是 safeUp() 方法。如果其中任意一个迁移提交失败了,那么这条命令将会退出并停止剩下的那些还未执行的迁移。

对于每一个成功提交的迁移,这条命令都会在一个叫做 migration 的数据库表中插入一条包含应用程序成功提交迁移的记录,该记录将帮助迁移工具判断哪些迁移已经提交, 哪些还没有提交。

提示:迁移工具将会自动在数据库当中创建 migration 表,该数据库是在该命令的 yii\console\controllers\MigrateController::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 表当中的某几行数据来表明数据库已经提交到了指定的某个迁移上。执行这条命令期间不会有任何的迁移会被提交或还原。

自定义迁移

有很多方法可以自定义迁移命令。

使用命令行选项

迁移命令附带了几个命令行选项,可以用来自定义它的行为:

interactive: boolean (默认值为 true),指定是否以交互模式来运行迁移。当被设置为 true 时,在命令执行某些操作前,会提示用户。如果你希望在后台执行该命令,那么你应该把它设置成 false。

migrationPath: string (默认值为 @app/migrations),指定存放所有迁移类文件的目录。该选项可以是一个目录的路径,也可以是 路径别名。需要注意的是指定的目录必选存在,否则将会触发一个错误。

migrationTable: string (默认值为 migration),指定用于存储迁移历史信息的数据库表名称。如果这张表不存在,那么迁移命令将自动创建这张表。当然你也可以使用这样的字段结构: version
 varchar(255) primary key, apply_time integer 来手动创建这张表。

db: string (默认值为 db),指定数据库 application component 的 ID。它指的是将会被该命令迁移的数据库。

templateFile: string (defaults to @yii/views/migration.php),指定生产迁移框架代码类文件的模版文件路径。该选项即可以使用文件路径来指定,也可以使用路径 别名 来指定。该模版文件是一个可以使用预定义变量 $className 来获取迁移类名称的 PHP 脚本。

如下例子向我们展示了如何使用这些选项:

例如,如果我们需要迁移一个 forum 模块,而该迁移文件放在该模块下的 migrations 目录当中,那么我们可以使用如下命令:

# 在 forum 模块中以非交互模式进行迁移
yii migrate --migrationPath=@app/modules/forum/migrations --interactive=0

全局配置命令

在运行迁移命令的时候每次都要重复的输入一些同样的参数会很烦人,这时候,你可以选择在应用程序配置当中进行全局配置,一劳永逸:

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() 代码。然后每个迁移类都继承这个基类就可以了。

提示:除了在 yii\db\Migration::db 参数当中进行设置以外,你还可以通过在迁移类中创建新的数据库连接来操作不同的数据库。然后通过这些连接再使用 DAO 方法 来操作不同的数据库。

另外一个可以让你迁移多个数据库的策略是把迁移存放到不同的目录下,然后你可以通过如下命令分别对不同的数据库进行迁移:

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

第一条命令将会把 @app/migrations/db1 目录下的迁移提交到 db1 数据库当中,第二条命令则会把 @app/migrations/db2 下的迁移提交到 db2 数据库当中,以此类推。

希望本文所述对大家基于Yii框架的PHP程序设计有所帮助。

PHP 相关文章推荐
模拟OICQ的实现思路和核心程序(三)
Oct 09 PHP
php 网页游戏开发入门教程一(webgame+design)
Oct 26 PHP
php生成的html meta和link标记在body标签里 顶部有个空行
May 18 PHP
php中获取指定IP的物理地址的代码(正则表达式)
Jun 23 PHP
基于wordpress主题制作的具体实现步骤
May 10 PHP
php取得字符串首字母的方法
Mar 25 PHP
php简单实现快速排序的方法
Apr 04 PHP
php实现根据词频生成tag云的方法
Apr 17 PHP
PHP中strpos、strstr和stripos、stristr函数分析
Jun 11 PHP
yii2高级应用之自定义组件实现全局使用图片上传功能的方法
Oct 08 PHP
详解php用curl调用接口方法,get和post两种方式
Jan 13 PHP
统计PHP目录中的文件数方法
Mar 05 PHP
yii2高级应用之自定义组件实现全局使用图片上传功能的方法
Oct 08 #PHP
ThinkPHP发送邮件示例代码
Oct 08 #PHP
Yii2针对游客、用户防范规则和限制的解决方法分析
Oct 08 #PHP
Netbeans 8.2与PHP相关的新特性介绍
Oct 08 #PHP
Laravel中基于Artisan View扩展包创建及删除应用视图文件的方法
Oct 08 #PHP
PHP反射API示例分享
Oct 08 #PHP
验证坐标在某坐标区域内php代码
Oct 08 #PHP
You might like
后宫无数却洁身自好的男主,唐三只爱小舞
2020/03/02 国漫
星际争霸 Starcraft 秘技补丁
2020/03/14 星际争霸
深入eAccelerator与memcached的区别详解
2013/06/06 PHP
php使用ZipArchive提示Fatal error: Class ZipArchive not found in的解决方法
2014/11/04 PHP
JQuery 学习笔记 选择器之二
2009/07/23 Javascript
45个JavaScript编程注意事项、技巧大全
2015/02/11 Javascript
jquery实现的美女拼图游戏实例
2015/05/04 Javascript
jQuery实现鼠标经过时出现隐藏层文字链接的方法
2015/10/12 Javascript
浅谈javascript基础之客户端事件驱动
2016/06/10 Javascript
JavaScript获取当前时间向前推三个月的方法示例
2017/02/04 Javascript
使用jQuery,Angular实现登录界面验证码详解
2017/04/27 jQuery
浅谈Vue.js中的v-on(事件处理)
2017/09/05 Javascript
vue组件通信传值操作示例
2019/01/08 Javascript
详解原生JS回到顶部
2019/03/25 Javascript
Vue实现页面添加水印功能
2019/11/09 Javascript
Python中isnumeric()方法的使用简介
2015/05/19 Python
解决Python字典写入文件出行首行有空格的问题
2017/09/27 Python
python和shell监控linux服务器的详细代码
2018/06/22 Python
对python实时得到鼠标位置的示例讲解
2018/10/14 Python
Python发送邮件测试报告操作实例详解
2018/12/08 Python
python制作图片缩略图
2019/04/30 Python
Python数据库封装实现代码示例解析
2020/09/05 Python
医疗保健专业人士购物网站:Scrubs & Beyond
2017/02/08 全球购物
介绍下WebSphere的安全性
2013/01/31 面试题
艺术爱好者的自我评价分享
2013/10/08 职场文书
教师自荐书
2013/10/08 职场文书
机修工岗位职责
2013/11/24 职场文书
职业女性的职业规划
2014/03/04 职场文书
商务经理岗位职责
2014/07/30 职场文书
2014个人反腐倡廉思想汇报
2014/09/15 职场文书
个人查摆剖析材料
2014/10/04 职场文书
六查六看自查报告
2014/10/14 职场文书
2014年图书馆个人工作总结
2014/12/18 职场文书
龙潭大峡谷导游词
2015/02/10 职场文书
春节慰问信范文
2015/02/15 职场文书
《作风建设永远在路上》心得体会
2016/01/21 职场文书