在我们开发程序的过程中,数据库的结构也是不断调整的。我们的开发中要保证代码和数据库库的同步。因为我们的应用离不开数据库。例如: 在开发过程中,我们经常需要增加一个新的表,或者我们后期投入运营的产品,可能需要为某一列添加索引。我们必须保持数据结构和代码的一致性。如果代码和数据库不同步,可能整个系统将无法正常运行。出于这个原因。yii提供了一个数据库迁移工具,可以保持代码和数据库是同步。方便数据库的回滚和更新。

下面的步骤说明了我们如何能够在开发过程中使用的数据库迁移:

  1. Tim 创建一个新的迁任务(例如,创建一个新表)
  2. 提交迁移后的新的源代码到控制系统(如SVN,GIT)
  3. Doug从源代码控制系统的更新了源代码并接收新的迁移
  4. Doug应用迁移到他的本地开发数据库

Note: 使用yiic迁移命令,最好切换到指定的应用程序目录(e.g. cd path/to/protected)而不是在框架根目录。

1. Creating Migrations  创建迁移

要创建一个新的迁移(例如,创建一个新闻表),我们运行下面的命令:

yiic migrate create <name>

name参数是必须的跟指定的迁移做非常简短的描述(例如create_news_table)。正如我们的例子,由于name参数是用来作为一个PHP类名称的一部分。因此,它应该只包含字母,数字和/或下划线字符。

yiic migrate create create_news_table

上面的命令将在目录protected/migrations下创建一个新的文件namedm101129_185401_create_news_table.php其中包含以下的初始代码:

class m101129_185401_create_news_table extends CDbMigration
{
public function up()
{
} public function down()
{
echo "m101129_185401_create_news_table does not support migration down.\n";
return false;
} /*
// implement safeUp/safeDown instead if transaction is needed
public function safeUp()
{
} public function safeDown()
{
}
*/
}

注意,创建迁移时类名作为文件名的格式是m<timestamp>_<name>,其中的<timestamp>是指UTC时间戳(yymmdd_hhmmss格式)和<name>通过命令参数指定。

up()方法应该包含实际的数据库迁移的实现代码,而down()方法是up()回滚代码。

有时, down()不指定具体代码。例如,如果我们在up()中删除表的行,我们将不能回滚up的操作。在这种情况下,迁移被称为不可逆的,这意味着我们不能回滚到以前的状态的数据库。在上述生成的代码,up()方法返回false表明,迁移无法恢复。

Info: 从版本1.1.7开始,如果 up() or down() 方法返回false,表示迁移被取消。此前1.1.6版本中,抛出异常取消迁移。

例子中介绍了一个创建新闻表的迁移。

class m101129_185401_create_news_table extends CDbMigration
{
public function up()
{
$this->createTable('tbl_news', array(
'id' => 'pk',
'title' => 'string NOT NULL',
'content' => 'text',
));
} public function down()
{
$this->dropTable('tbl_news');
}
}

基类CDbMigration提供了一套用于操纵数据和数据库的结构的方法。例如, CDbMigration::createTable将创建一个数据库表,而CDbMigration::insert将插入一行数据。这些方法都使用CDbMigration::getDbConnection()获取数据库连接,默认返回Yii::app()->db

Info: 您可能会注意到由CDbMigration数据库提供的方法和CDbCommand非常相似。事实上,他们几乎是相同的,除了CDbMigration方法将打印方法所用的时间和打印有关该方法的参数的一些消息。

2. Transactional Migrations 事务迁移

Info: 版本1.1.7后支持事务迁移功能。

执行复杂的数据库迁移的同时,我们通常要确保整个迁移成功或失败,从而使数据库保持一致性和完整性。为了实现这个目标,我们可以利用数据库的事务。

我们应该明确地指定启动DB 事务和事务相关的数据的代码的操作,例如:

class m101129_185401_create_news_table extends CDbMigration
{
public function up()
{
$transaction=$this->getDbConnection()->beginTransaction();
try
{
$this->createTable('tbl_news', array(
'id' => 'pk',
'title' => 'string NOT NULL',
'content' => 'text',
));
$transaction->commit();
}
catch(Exception $e)
{
echo "Exception: ".$e->getMessage()."\n";
$transaction->rollback();
return false;
}
} // ...similar code for down()
}

获得事务支持一个更简单的方式是使用safeUp() 方法代替up(),safeDown() 代替down()。例如,

class m101129_185401_create_news_table extends CDbMigration
{
public function safeUp()
{
$this->createTable('tbl_news', array(
'id' => 'pk',
'title' => 'string NOT NULL',
'content' => 'text',
));
} public function safeDown()
{
$this->dropTable('tbl_news');
}
}

Yii的执行迁移时,它会启动一个数据库事务,然后调用safeUp()或safeDown()。如果任何DB错误safeUp()或safeDown()时,将回滚事务,从而确保数据库完整性。

Note: 不是所有的DBMS都支持事务。一些数据库查询不能放入事务。在这种情况下,您不得不使用up() 和down()。MySQL中,一些SQL语句可能会造成隐式提交。

3. Applying Migrations 应用迁移

应用所有可用的新的迁移(例如, 本地数据库最新),运行以下命令:

yiic migrate

该命令将显示所有新迁移的名单。如果确认应用迁移,它将运行那些up()方法执行迁移,执行顺序是按照类名的时间戳值的顺序。

在应用迁移是,迁移工具将保存记录到名为tbl_migration数据库表中。这使得该工具,可以确保那些迁移被应用。如果tbl_migration不存在,该工具会自动在DB应用程序指定的数据库中创建它

有时候,我们可能仅仅需要应用一个或几个新的迁移。我们可以用下面的命令:

yiic migrate up 3

此命令将应用3个新的迁移。通过修改值3,将允许我们改变应用的迁移的数目。

我们也可以用下面的命令迁移到特定版本的数据库:

yiic migrate to 101129_185401

也就是说,我们可以使用迁移名称+时间戳部分来指定我们要迁移的数据库的版本。如果有多个迁移例如最后一次应用的迁移和指定的迁移。所有这些迁移都会被应用。先应用最后一个迁移,然后再回滚指定的迁移(将在一节中所述)。

4. Reverting Migrations 还原迁移

要恢复过去的一个或多个应用的迁移,我们可以使用下面的命令:

yiic migrate down [step]

可选 step 参数指定恢复多少迁移。默认值为1,这意味着回滚最后一次迁移。

正如我们前面所述,并非所有的迁移都可以被回滚。试图回滚这样的迁移将抛出一个异常并停止整个恢复过程。

5. Redoing Migrations

重做迁移意味着首先恢复和再应用指定的迁移。这可以用下面的命令:

yiic migrate redo [step]

可选step参数指定重做多少迁移。默认值为1,这意味着重做最后的迁移。

6. Showing Migration Information 显示迁移信息

除了应用和恢复迁移,还可以显示迁移的历史和应用的新迁移。

yiic migrate history [limit]
yiic migrate new [limit]

其中,可选参数限制指定要显示的迁移。如果没有指定的限制,将显示所有可用的迁移。

第一条命令显示已应用的迁移,而第二个命令显示尚未应用的迁移。

7. Modifying Migration History

有时候,我们可能要修改移民记录,这通常发生在没有实际应用或恢复有关迁移到一个特定的迁移版本或在开发一个新的迁移任务时。我们可以用下面的命令来实现。

yiic migrate mark 101129_185401

此命令和yiic迁移命令非常相似,除了它只能修改历史记录表,没有应用迁移或恢复迁移到指定的版本。

8. Customizing Migration Command 定制迁移命令

有几种方法来定制迁移命令。

Use Command Line Options 使用命令行选项

在命令行中迁移命令可以使用如下四个选项:

  • interactive: boolean,指定是否执行交互模式的迁移。默认为true,这意味着用户将被提示时执行特定迁移。您可以设置为false应该在做一个后台进程迁移

  • migrationPath: string,指定存储所有迁移的类文件的目录。必须指定路径别名以及相应的目录必须存在。如果没有指定,它将使用应用程序的根路径下的themigrations子目录

  • migrationTable: string,,指定存储迁移历史信息的数据库表的名称。默认tbl_migration。表的结构是版本VARCHAR(255)主键,apply_time整数。

  • connectionID: string,指定的数据库应用程序组件的ID。默认为'DB'。

  • templateFile: string,指定文件的路径,作为担任产生迁移类的代码模板。这必须指定一个路径别名(eg application.migrations.template)。如果没有设置,将使用一个内部模板。在该模板中,标记{ClassName}将被替换为实际的迁移类的名称。

实例如下

yiic migrate up --option1=value1 --option2=value2 ...

例如,如果我们要迁移的一个论坛模块,其迁移位于模块的migrations目录内的文件,我们可以使用下面的命令:

yiic migrate up --migrationPath=ext.forum.migrations

Configure Command Globally 配置全局命令

虽然命令行选项允许我们配置迁移命令,有时我们可能需要一次配置所有的命令。例如,我们可能要使用不同的表来存储迁移历史,或者我们可能要使用一个定制的迁移模板。我们可以通过类似下面的控制台应用程序的配置文件修改,

return array(
......
'commandMap'=>array(
'migrate'=>array(
'class'=>'system.cli.commands.MigrateCommand',
'migrationPath'=>'application.migrations',
'migrationTable'=>'tbl_migration',
'connectionID'=>'db',
'templateFile'=>'application.migrations.template',
),
......
),
......
);

现在,如果我们运行migrate命令,上述配置将一直有效,而无需每次配置。

数据库迁移 使用命令行..执行的是console/Application

所以要更改console/config下的配置...

'components.db'=>[
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=test',
'username' => 'root',
'password' => '******',
]

  • php yii migrate --migrationPath=@vendor/amnah/yii2-user/amnah/yii2/user/migrations

yii 数据库迁移的更多相关文章

  1. migrate数据库迁移

    可先参看博友的博文:https://segmentfault.com/a/1190000005599416 由于Yii migrate 生成的迁移文件默认是存放在 console/migrations ...

  2. EF Code First Migrations数据库迁移

    1.EF Code First创建数据库 新建控制台应用程序Portal,通过程序包管理器控制台添加EntityFramework. 在程序包管理器控制台中执行以下语句,安装EntityFramewo ...

  3. 2.EF中 Code-First 方式的数据库迁移

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/code-first-migrations-with-entity-framework/ 系列目 ...

  4. laravel数据库迁移(三)

    laravel号称世界上最好的框架,数据库迁移算上一个,在这里先简单入个门: laravel很强大,它把表中的操作写成了migrations迁移文件,然后可以直接通过迁移文件来操作表.所以 , 数据迁 ...

  5. Code First开发系列之数据库迁移

    返回<8天掌握EF的Code First开发>总目录 本篇目录 开启并运行迁移 使用迁移API 应用迁移 给已存在的数据库添加迁移 EF的其他功能 本章小结 自我测试 本系列的源码本人已托 ...

  6. ABP Migration(数据库迁移)

    今天准备说说EntityFramework 6.0+,它与我之前所学的4.0有所区别,自从4.1发布以来,code first 被许多人所钟爱,Dbcontext API也由此时而生.早在学校的时候就 ...

  7. sqlserver 2008R2数据库迁移oracle

    x项目需要,将以前的sqlserver数据库迁移的oracle数据库中,由于以前对oracle只是在DML语句的步骤,所以总结一下这次遇到的问题以及具体步骤 1,oracle新建数据库 新建Oracl ...

  8. 【强烈推荐】数据库迁移利器:Migrator.Net

    简介 很郁闷,写了一天的遇到LiveWriter错误,可恶啊 几年前在做项目中第一次接触到了Migrator.Net,就深深被吸引住了,至此以后在新的大项目中,我都会使用Migrator.Net来创建 ...

  9. ubuntu系统lamp环境搭建、数据库迁移、设置数据库外部访问

    sudo passwd root设置两次密码su输入设置的密码exit (退出root帐号) 1.sudo apt-get update 2.sudo apt-get install apache2 ...

随机推荐

  1. OK335xS tmp75 Qt 温度读取

    /******************************************************************* * OK335xS tmp75 Qt 温度读取 * 说明: * ...

  2. OK335xS LAN8710 phy driver hacking

    /******************************************************************** * OK335xS LAN8710 phy driver h ...

  3. c语言之extern关键字

    1.定义 extern,外面的.外来的意思.那它有什么作用呢?举个例子:假设你在大街上看到一个黑皮肤绿眼睛红头发的美女(外星人?)或者帅哥.你的第一反应就是这人不是国产的. extern就相当于他们的 ...

  4. Java这点事

    1--代码片段:  1 2 3 4 5 byte b1=1,b2=2,b3,b6;  final byte b4=4,b5=6;  b6=b4+b5;  b3=(b1+b2);  System.out ...

  5. jQuery.Validate验证库

    一.用前必备官方网站:http://bassistance.de/jquery-plugins/jquery-plugin-validation/ API: http://jquery.bassist ...

  6. FAT32文件系统--For TF卡

    1. TF卡空间是如何分配的? 下面以4GB TF卡为例,通过WinHex工具进行分析,其空间分配如下图所示: FAT32把目录当做文件来管理,所以没有独立的目录区,所有的文件目录项都是在数据区里面的 ...

  7. POJ 2828-Buy Tickets(线段树)

    题意: 有n个人,每人有一定的价值,给n个安排,每次安排有两个数 p,v p是这个人前面人的个数 (直接插在第p个人后面其他人后移),v是它的价值,n个安排后 求最终的价值序列. 分析: 越在后面的安 ...

  8. HDU4289 Control 最大流

    经典题,求去掉若干个点,使得两个点不在连通,总价值最少 所以拆点最小割,除了拆点边,流量都为无穷,拆点边是流量为价值 #include <iostream> #include <cs ...

  9. HDU 3001 Travelling 3进制状压dp

    题意:10个点,若干条边,边有花费,每个点最多走两次,求走过所有点,花费最少 分析:因为每个点最多走两次,所以联想到3进制,然后枚举状态,就行了(我也是照着网上大神的代码写的) #include &l ...

  10. Python脚本控制的WebDriver 常用操作 <五> 访问链接

    下面将使用webdriver来访问一个web链接 测试用例场景 测试中,经常会点击几个链接来进行操作,所以访问链接是基本的常见操作 Python脚本 from selenium import webd ...