哈囉,大家好!在上一篇文章中,我們成功地使用 Laravel 的 Migration 建立了資料庫結構。現在,是時候來探索 Laravel 中的另一個重要組件:Model(模型)。透過 Model,我們可以輕鬆地與資料庫互動,實現資料的讀取、寫入和關聯操作。
在 Laravel 中,Model 是應用程式與資料庫之間的橋樑。它使用了 Eloquent ORM(Object-Relational Mapping),讓我們可以用物件的方式來操作資料庫,而不需要撰寫繁瑣的 SQL 語句。
個人經驗分享:還記得剛開始接觸 Laravel 時,對 Eloquent ORM 感到驚艷。以前需要寫大量的 SQL 語句,現在只需幾行程式碼就能完成。同時,程式碼的可讀性也大大提升,讓開發變得更輕鬆有趣。
Laravel 提供了 Artisan 命令列工具,讓我們可以快速地生成 Model。
在終端機中執行以下指令:
php artisan make:model User
這將在 app/Models 目錄下建立一個 User.php 的檔案。
小提醒:Laravel 8 之後,Model 預設存放在 app/Models 目錄下。如果你使用的是較舊的版本,Model 可能位於 app 目錄下。
按照同樣的方式,為我們的資料表建立相應的 Model。
php artisan make:model BankAccount
php artisan make:model Category
php artisan make:model Transaction
現在,我們已經為每個資料表建立了對應的 Model。接下來,讓我們來設定這些 Model,使其與資料表正確對應。
Laravel 的 Eloquent 會自動推斷資料表名稱,例如,User Model 對應到 users 資料表。但有時候,我們的資料表名稱可能與預設規則不符,這時需要在 Model 中明確指定。
舉例來說,如果我們的資料表名稱是 bank_accounts,Eloquent 會自動將 BankAccount Model 對應到 bank_accounts 資料表。但為了保險起見,我們可以在 Model 中指定:
class BankAccount extends Model
{
protected $table = 'bank_accounts';
}
如果資料表的主鍵名稱不是 id,需要在 Model 中指定主鍵欄位。例如:
class User extends Model
{
protected $primaryKey = 'user_id';
}
如果資料表中沒有 created_at 和 updated_at 欄位,可以在 Model 中關閉時間戳記:
class Category extends Model
{
public $timestamps = false;
}
資料表之間的關聯可以透過 Model 來定義,這是 Eloquent 強大的地方。接下來,我們將為各個 Model 定義關聯關係。
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
// 一個使用者有多個銀行帳戶
public function bankAccounts()
{
return $this->hasMany(BankAccount::class);
}
// 一個使用者有多個分類
public function categories()
{
return $this->hasMany(Category::class);
}
// 一個使用者有多筆交易
public function transactions()
{
return $this->hasMany(Transaction::class);
}
}
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class BankAccount extends Model
{
// 屬於一個使用者
public function user()
{
return $this->belongsTo(User::class);
}
// 一個銀行帳戶有多筆交易
public function transactions()
{
return $this->hasMany(Transaction::class);
}
}
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
// 屬於一個使用者
public function user()
{
return $this->belongsTo(User::class);
}
// 一個分類有多筆交易
public function transactions()
{
return $this->hasMany(Transaction::class);
}
}
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Transaction extends Model
{
// 屬於一個使用者
public function user()
{
return $this->belongsTo(User::class);
}
// 屬於一個銀行帳戶
public function bankAccount()
{
return $this->belongsTo(BankAccount::class);
}
// 屬於一個分類
public function category()
{
return $this->belongsTo(Category::class);
}
}
現在,我們已經設定好了 Model 和關聯關係。接下來,讓我們來看看如何使用 Model 進行資料庫操作。
$user = new User();
$user->username = 'john_doe';
$user->email = 'john@example.com';
$user->password = bcrypt('secret');
$user->save();
$bankAccount = new BankAccount();
$bankAccount->account_name = '薪資帳戶';
$bankAccount->account_number = '123456789';
$bankAccount->bank_name = '台灣銀行';
// 關聯到使用者
$user->bankAccounts()->save($bankAccount);
$user = User::find(1);
$bankAccounts = $user->bankAccounts;
$transaction = Transaction::with(['user', 'bankAccount', 'category'])->find(1);
$bankAccount = BankAccount::find(1);
$bankAccount->balance += 5000;
$bankAccount->save();
$category = Category::find(1);
$category->delete();
$transaction = new Transaction([
'type' => 'expense',
'amount' => 2000,
'transaction_date' => now(),
'description' => '購買書籍',
]);
$user->transactions()->save($transaction);
Eloquent 提供了強大的查詢構建器,可以方便地進行各種複雜查詢。
$totalIncome = Transaction::where('user_id', $user->id)
->where('type', 'income')
->whereBetween('transaction_date', [$startDate, $endDate])
->sum('amount');
可以在 Model 中定義 Scope,讓常用的查詢條件更簡潔。
public function scopeIncome($query)
{
return $query->where('type', 'income');
}
public function scopeExpense($query)
{
return $query->where('type', 'expense');
}
$totalIncome = Transaction::income()->sum('amount');
$totalExpense = Transaction::expense()->sum('amount');
可以在 Model 中定義 Mutators 和 Accessors,對欄位的值進行修改或格式化。
在模型中定義了一個名為 setPasswordAttribute 的方法時,這個方法會被自動觸發,因為 Laravel 提供了一個特性,允許開發者為模型屬性定義 "setter" 方法。這個 "setter" 方法會在你試圖為模型的屬性賦值時自動調用。
public function setPasswordAttribute($value)
{
$this->attributes['password'] = bcrypt($value);
}
這樣,當我們設定使用者密碼時,會自動進行加密:
$user->password = 'new_password'; // 會自動加密
具體原因:
透過本篇文章,我們深入了解了 Laravel 的 Model 以及如何使用 Eloquent ORM 與資料庫進行互動。我們明白了:
But… 光是Model 就有很多可以講,但我們不要讓篇幅太多冗長,所以內容未來有機會,會在某個環節提出分享
我們將開始開發後端 API,這部分開始會連通幾個關鍵行為,這樣會比較有脈絡。讓我們繼續這段充滿挑戰與樂趣的開發之旅吧!