前言
前陣子遇到同一套系統需發佈在不同國家機房的需求,
其中資料庫 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
對資料表的操作,有些行為屬移除性質,會造成對應資料丟失,使用者應先於測試或開發環境驗證後,再施用於線上環境。
鍵盤錄影
讀者手邊若無操作環境,可參考鍵盤錄影。
全螢幕播放可得到最佳效果。