前言
前陣子遇到同一套系統需發佈在不同國家機房的需求,
其中資料庫 table schema 的更新似乎沒有比較聰明的作法,
因此只能將差異記錄成腳本,由 DBA 手動於各資料庫執行。
最近接觸的 Laravel Migrations 恰好能解決上述情境。
Migrations 簡介
Migrations 就像資料庫的版本控管,它讓開發團隊得以輕鬆地修改並分享 table schema。
Laravel 的 Schema facade 支援表格建立與操作,通用於各種資料庫,目前支援 MySQL/PostgreSQL/SQLite/SQL Server 等。(至於萬惡的 Oracle,有非官方套件可裝)
因此,開發者可使用程式碼逐行表達資料表的建立過程,包含各欄位的屬性與資料表間的關聯。
實作範例
準備工作
先以 Laravel Homestead 架設好三組機器作為多資料庫的環境。
資料庫的帳號、密碼與權限必須先設好,此為 DBA 職掌而非 Migrations 所能代勞的。
MySQL 指令如下:
CREATE USER 'homestead'@'%' IDENTIFIED BY 'secret'; CREATE DATABASE homestead; GRANT ALL ON homestead.* TO 'homestead'@'%';
以程式碼描述 table schema
以 users 資料表為例,它的 migrations 節錄如下:
<?php
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('username');
$table->string('email')->unique();
$table->string('password', 60);
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('users');
}
}
?>
其中 up 函式描述了資料表的組成,包含:
- id 欄位自動遞增
- username 欄位類型為字串
- email 欄位類型為字串,且不得重複
- password 欄位類型為字串,且長度限制為 60
- rememberToken 函式產生儲存 session 的特殊欄位
- timestamps 函式自動產生
created_at與updated_at欄位
down 函式則載明回復操作的步驟。
組態檔
各資料庫的連線組態,依慣例應寫入環境變數,並於 config/database.php 載入:
<?php
'connections' => [
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
'mysql-tw' => [
'driver' => 'mysql',
'host' => env('DB_HOST_TW', 'localhost'),
'database' => env('DB_DATABASE_TW', 'forge'),
'username' => env('DB_USERNAME_TW', 'forge'),
'password' => env('DB_PASSWORD_TW', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
'mysql-us' => [
'driver' => 'mysql',
'host' => env('DB_HOST_US', 'localhost'),
'database' => env('DB_DATABASE_US', 'forge'),
'username' => env('DB_USERNAME_US', 'forge'),
'password' => env('DB_PASSWORD_US', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
],
?>
實地操作
對於新建的資料表,可用 migrate 選項發佈 table schema
for DB_NAME in mysql mysql-tw mysql-us;
do
./artisan migrate --database ${DB_NAME}
done
若資料表已存在,可用 migrate:refresh 選項更新 table schema
for DB_NAME in mysql mysql-tw mysql-us;
do
./artisan migrate:refresh --database ${DB_NAME}
done
結語
Laravel Migrations 實作了 Active Record 的諸多要件。
對開發者,資料表異動可用程式碼描述並輕鬆分享;對維運者或 DBA,資料表異動受版本控管,可快速比較差異並於各版本間切換。
注意事項
Migrations 對資料表的操作,有些行為屬移除性質,會造成對應資料丟失,使用者應先於測試或開發環境驗證後,再施用於線上環境。
鍵盤錄影
讀者手邊若無操作環境,可參考鍵盤錄影。
全螢幕播放可得到最佳效果。