哈囉,大家好!經過前面的努力,我們已經為個人財務管理系統設計了完整的資料庫結構。現在,是時候將這些設計實際落地到 Laravel 框架中了。
今天,我們要一起探索 Laravel 中非常重要的一環:Migration(資料庫遷移)。
相信我,掌握了 Migration,不僅能讓你更有效地管理資料庫,還能讓你在開發過程中更加游刃有餘。讓我們一起揭開 Migration 的神秘面紗吧!
Migration 是 Laravel 提供的一種資料庫管理工具,它讓你可以用程式碼的方式定義和修改資料庫結構。簡單來說,Migration 就像是資料庫的版本控制,讓你可以方便地同步團隊之間的資料庫變更。
個人經驗分享:還記得剛開始開發時,手動修改資料庫結構總是帶來各種麻煩。自從使用了 Migration,一切變得有條不紊,在開發上也更加順暢。
Laravel 提供了 Artisan CLI(命令列介面)來幫助我們生成 Migration 檔案。讓我們來為 users 表建立一個 Migration。
在終端機中進入專案的根目錄,執行以下指令:等等……你有發現 database/migrations 目錄下,已經有一個 create_users_table.php 檔案嗎?這個檔案就是預設的 users 資料表結構:
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Schema::create('password_reset_tokens', function (Blueprint $table) {
$table->string('email')->primary();
$table->string('token');
$table->timestamp('created_at')->nullable();
});
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->primary();
$table->foreignId('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->longText('payload');
$table->integer('last_activity')->index();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('users');
Schema::dropIfExists('password_reset_tokens');
Schema::dropIfExists('sessions');
}
這比我們預先規劃的多了兩張表,而且 users 的結構有幾個地方不一樣。所以在我們開始編輯 Migration 檔案前,先來介紹 Schema Builder 的相關用法。
Laravel 的 Schema Builder 是一個強大的工具,讓你可以使用 PHP 語法來定義資料庫的結構,而不需要直接撰寫 SQL 語句。這使得程式碼更具可讀性,也更容易維護。
以下是一些常用的 Schema Builder 方法,以及它們對應的 MySQL 資料型態:
小提醒:Laravel 的 Schema Builder 提供了許多方便的方法,詳細可以參考官方文件,多加了解絕對不會吃虧!
打開預設的 create_users_table.php 檔案,你會看到 up 和 down 兩個方法。
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('username', 50)->unique();
$table->string('email', 100)->unique();
$table->string('password');
$table->timestamps();
});
}
在這裡,我們使用了 Laravel 的 Schema Builder 來定義資料表的結構,並移除了我們不需要的欄位。
寫下來我們所執行的指令都是在Laravel 容器內執行,如果忘記怎麼進入容器的終端環境,請回去參考D5喔
接下來,按照同樣的步驟,為其他資料表建立 Migration。
執行指令:
php artisan make:migration create_bank_accounts_table --create=bank_accounts
編輯生成的 Migration 檔案:
public function up()
{
Schema::create('bank_accounts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->string('account_name', 100);
$table->string('account_number', 50)->nullable();
$table->string('bank_name', 100)->nullable();
$table->decimal('balance', 15, 2)->default(0.00);
$table->timestamps();
// 外鍵約束
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
執行指令:
php artisan make:migration create_categories_table --create=categories
編輯生成的 Migration 檔案:
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->string('category_name', 100);
$table->enum('type', ['income', 'expense']);
$table->timestamps();
// 外鍵約束
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
執行指令:
php artisan make:migration create_transactions_table --create=transactions
編輯生成的 Migration 檔案:
public function up()
{
Schema::create('transactions', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('bank_account_id');
$table->unsignedBigInteger('category_id');
$table->enum('type', ['income', 'expense']);
$table->decimal('amount', 15, 2);
$table->date('transaction_date');
$table->string('description', 255)->nullable();
$table->timestamps();
// 外鍵約束
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('bank_account_id')->references('id')->on('bank_accounts')->onDelete('cascade');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
});
}
所有 Migration 檔案都準備好了,現在讓我們來執行它們,實際建立資料表。
在終端機中執行:
php artisan migrate
如果一切順利,終端機會顯示 Migration 已成功執行。
個人經驗分享:有時候執行 Migration 時會遇到錯誤,通常是因為資料表之間的關聯順序問題。例如,transactions 表需要 users、bank_accounts 和 categories 表已經存在。所以在編寫 Migration 時,注意資料表的建立順序很重要。
為了確保 Migration 按照正確的順序執行,可以在 Migration 檔案的開頭加上時間戳,使其按照時間順序排列。
例如,在 Migration 檔案名稱前面添加時間戳:
如果發現 Migration 有錯誤,需要回滾,執行:
php artisan migrate:rollback
這會回滾最近一次的 Migration。
在開發階段,你可能需要修改已經建立的 Migration。常見的做法是:
php artisan migrate:rollback
php artisan migrate
小提醒:在正式環境中,不建議直接修改已經執行的 Migration,而是應該建立新的 Migration 來修改資料表結構。
為了測試,我們可以使用 Laravel 的 Seeder 來填充一些測試資料。
執行指令:
php artisan make:seeder UsersTableSeeder
這會在 database/seeders 目錄下生成一個 UsersTableSeeder.php 檔案。
打開 UsersTableSeeder.php,填寫以下內容:
public function run()
{
User::factory()->create([
'username' => 'testuser',
'email' => '[email protected]',
'password' => bcrypt('password'),
'created_at' => now(),
'updated_at' => now(),
]);
}
在 DatabaseSeeder.php 中,呼叫剛剛建立的 Seeder:
public function run()
{
$this->call(UsersTableSeeder::class);
}
執行 Seeder:
php artisan db:seed
這樣,我們就為 users 表填充了一筆測試資料。
今天,我們深入了解了 Laravel 的 Migration,並實際建立了我們之前設計的資料表。透過 Migration,我們可以:
個人經驗分享:一開始接觸 Migration 時,可能會覺得多此一舉,但當你經歷過手動修改資料庫帶來的痛苦後,你就會發現 Migration 是多麼的可靠和方便。
在完成資料表的建立後,接下來我們將:建立模型(Models),與資料表進行互動!