注意,數據遷移這玩意1.1.6以後纔可以用哦。另外,說一下,英文是migrate,翻譯爲遷移,但是我看大部分是數據庫的變更操作而已啊。
就跟源代碼一樣的,數據庫結構在我們開發維護數據庫驅動應用的同時,也在發展着。例如,在我們開發的時候,我們會想新創建一個數據庫的表,或者是在開發完成,項目上線後,才發現要給某個字段加一個索引。很重要的一點,必須記錄跟蹤這些數據庫結構方面的變化(遷移)。如果源代碼或者是數據庫不一致了,整個系統都很有可能被破壞了。出於這個原因,Yii提供了一個數據庫遷移工具,可以記錄數據庫的變化記錄,應用新的架構,或者是回滾到之前的架構。
以下步驟演示了我們在開發時如何使用數據遷移的工具:
1. 張三創建了一個新的變更(例如,創建了張表)
2. 張三把這個變更提交到了SVN。
3. 李四從SVN獲得更新後的結構。
4. 李四把這些更新應用到他自己本地的數據庫。
Yii通過調用yiic migrate的命令行工具來實現數據遷移的。這個工具支持新建數據庫遷移,應用,回滾,重做。可以查看遷移記錄,以及查看最新的鏡像。
接下來,我們將介紹怎麼使用這個工具。
注意:最好是用工程下的yiic,而不要用框架下的yiic命令。確保你的protected\migrations存在,並且目錄可寫。同時,還要檢查你的數據庫連接protected/config/console.php。
1.1 創建遷移
要創建一個新的變更,執行以下命令即可:
yiic migrate create <name>
name參數是制定一個很簡短的關於這個新遷移的描述,例如create_news_table。下面我們會看到,name就像是用一個PHP的類名。所以,只允許包含字母,數字或者是下劃線。
yiic migrate create create_news_table
上面的命令,會在protected/migrations目錄下,創建一個名爲m101129_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.nn";
- return false;
- }
- /*
- // implement safeUp/safeDown instead if transaction is needed
- public function safeUp()
- {
- }
- public function safeDown()
- {
- }
- */
- }
注意到,上面類名跟文件是同名的,命名規則爲m<timestamp>_<name>。<timestamp>是UTC的時間戳(格式爲yymmdd_hhmmss)。
up()方法裏面包含了這次遷移所要做的實際動作;down()方法裏,包含了回滾需要做的操作。
有些時候,是沒有辦法做回滾的。例如,我們在up時刪除了一張數據表,我們在down的時候就沒有辦法恢復了。在這種情況下,遷移就被稱之爲不可逆的,意味着我們無法回滾到數據庫之前的那個狀態中。在上面的例子中,down()方法返回false,表示無法回滾。
INFO:從1.1.7版本開始,如果up或者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的命令。事實如此。
1.2 數據庫變遷事務
INFO:次功能是從yii的1.1.7 版本開始才支持
當執行復雜的數據庫變遷時,我們希望每個變動都是同時成功或者失敗,這樣可以保證數據庫的一致性。要做到這點,就用我們之前提到過的數據庫事務。
我們在開始的時候使用事務,然後在所有動作之後,結束事務:
- 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()."nn";
- $transaction->rollBack();
- return false;
- }
- }
- // ...similar code for down()
- }
或者是,採用更加簡便的方法,用safeUp(),safeDown() 替換up()以及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())。如果在這兩個方法中有任何的錯誤,事務就會回滾,保證數據庫的完整性。
注意:並不是所有的數據庫系統都支持事務操作,另外,還有一些操作不能用在事務中。這種情況下,就要用up()跟down()了。在MYSQL當中,有些語句會被隱式提交的。
1.3 應用變遷
如果想應用所有的新變更,執行以下的語句:
yiic migrate
這個指令會列出所有新的變遷,如果你確定應用這些變遷,就會調用這些變遷類當中的up()方法,按照時間順序一個一個的執行。
當一個變遷應用以後,變遷工具就會在數據庫中的一個名爲tbl_migration表中,生成一條記錄。這條記錄用來幫助變遷工具辨別哪些變遷已經應用了,哪些還沒有。如果tbl_migration的表不存在,變遷工具會自動在數據庫創建一張。
有時候,我們只想更新一個或者是部分的變遷,我們可以用這個命令:
yiic migrate up 3
這個命令會應用3個新的變遷,當然我們可以更改3這個數字來決定應用幾個。
當然,我們也可以指定應用到哪個新變遷爲止:
yiic migrate to 101129_185401
上面方法中,我們用時間戳來指定我們想應用的變遷。如果從上次應用的變遷,到這個指定的變遷,中間還有許多沒應用的,所有這些都會被應用。如果這個指定的變遷是被應用過的,那麼這個之後的所有應用過的變遷都會被回滾。
1.4 回滾應用變遷
如果要回滾上一次或者是很多次之前的變遷,用以下的命令:
yiic migrate down [step]
step 代表想回滾應用的變遷數量,默認值是1, 也就是回滾到上一次的應用變遷前。
正如我們之前提到過的,並不是所有被應用過的變遷都可以回滾。如果嘗試回滾這樣的變遷,整個回滾都會終止。
1.5 重做變遷
重做,也就是之前應用過,回滾過,現在又要重新應用。可以按照以下的命令:
yiic migrate redo [step]
step的參數跟上面回滾是一樣的。
1.6 查詢變遷信息
除了應用,回滾數據庫變遷,這個變遷工具還可以用來查詢應用的變遷記錄信息。
yiic migrate history [limit]
yiic migrate new [limit]
參數limit指定了查詢的個數,如果沒指定該參數值,所有的變遷記錄都會被查詢出來。
第一個命令列出被應用過的變遷,第二個列出沒被應用過的。
1.7 修改變遷記錄
有時候,我們想修改這個變遷記錄的版本,但是又不真的去應用或者回滾該變遷。這經常發生於我們開發新的變遷時,我們可以用以下的命令來實現:
yiic migrate mark 101129_185401
這個指令跟yiic migrate非常相似,區別在於這個命令只是修改了數據庫中記錄的變遷記錄,實際上並沒有應用或者回滾該操作。
1.8 自定義變遷指令
有許多方式可以自定義變遷指令。
用命令行選項
命令行中,有4個選項可以用來自定義:
●interactive:boolean型。用來指定應用變遷時,是否採用互動模式。默認值是true,也就是在應用時,會提醒用戶。如果是false,那麼就是在後臺執行。
●migrationPath:string型。指定變遷類文件的存放路徑。這個路徑必須用別名的方式,而且必須存在。如果不存在,則會用工程下的migrations子目錄。
●migrationTable:string型。指定數據庫中的變遷記錄表。默認值是tbl_migration。表結構是version varchar(255) primary key, apply time integer。
●connectionID:string型。指定數據庫連接句柄,默認是db。
●templateFile:string型。指定生成變遷類時的代碼模板路徑。同樣的,需要路徑別名的格式。如果不存在,則內置的模板會被使用。
要指定這些選項,調用變遷指令時,用以下的格式:
yiic migrate up --option1=value1 --option2=value2 ...
例如,我們要從forum模塊下的變遷文件來應用,可以用下面的代碼:
yiic migrate up --migrationPath=ext.forum.migrations
設置全局命令
雖然命令行的選項讓我們可以在用的時候你可以有選擇,但是有時候我們想一次性就配置好。例如,我們想用另外的一張表來保存變遷記錄,或者我們想用一個自定義的變遷模板,我們可以在工程的控制面板進行工程:
- return array(
- ......
- 'commandMap'=>array(
- 'migrate'=>array(
- 'class'=>'system.cli.commands.MigrateCommand',
- 'migrationPath'=>'application.migrations',
- 'migrationTable'=>'tbl migration',
- 'connectionID'=>'db',
- 'templateFile'=>'application.migrations.template',
- ),
- ......
- ),
- ......
- );
這時候,當我們調用migrate的命令行時,上面的選項配置就會生效了。