hasOne
跟 belongsTo
都是 Laravel Eloquent 所提供的方法,負責處理一對一的關係。
那一樣都是一對一,這兩個用法的差別在哪裡呢?簡單來說是這樣:
hasOne
指的是「擁有一個東西」,我擁有一個東西,我在它的身上貼上了我的名字。
belongsTo
指的是「屬於某個人」,我屬於別人,我被貼上了他的名字。
我們來看下面的範例,
假設我們有兩張 Table,分別是 users
及 cars
,在 Laravel中,分別會對應到 User
及 Car
兩個 Model。
我們設定的關係是,每個人只能擁有一輛車,反過來說,每輛車只能被一個人擁有。
在 User
Model中,car
method 使用 hasOne
, 因為在 User
Model 中,主體是 User
。
現在我們來解讀 car
method return 的那段程式:
$this->hasOne(Car::class)
$this
在這邊指的是 user ,因此這行程式直接讀起來就是:User has one car,使用者擁有一輛車,應該還蠻直觀的吧!
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function car()
{
return $this->hasOne(Car::class);
}
}
再來看 Car Model
,user
method 使用 belongsTo
,因為是在 Car
Model 中,主體是 Car
,因此user
method 的語意是: Car belongs to (a) user,車子屬於一個使用者。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Car extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
從語意的層面來看,好像都蠻正常的,但一般來說,我們會有一個問題:既然都是一對一的用法,那為什麼不能兩個都用 hasOne
或是都用 belongsTo
,或是甚至反過來用呢?
這就是關鍵所在了,要回答這個問題就要回到開頭講的,
hasOne
指的是「有一個」,我有一個東西,我在它身上貼上了我的名字。
belongsTo
指的是「屬於某個人」,我屬於別人,我被貼上了他的名字。
重點是誰被貼上了名字。
在資料庫領域中,被貼上名字這件事其實指的就是 foreign key, FK
,也就是外鍵,被貼上名字的東西,它的 Table 上會有一欄 foreign key
,用來記錄所屬者的 primary key, PK
。
因此,當 foreign key
在誰身上,就代表它被貼上名字,它是屬於某個人的,它就要使用 belongsTo
去找到主人,而另一方就要使用 hasOne
去找到他的東西。
這時我們再回看看 User
及 Car
的範例,可以看到Car
使用 belongsTo
去建立跟 User
的關係,套用剛剛的討論,是 Car
被貼上了名字,因此是 cars
有一欄 foreign key
儲存了對應的 users
table 的 primary key
。
補充:
Laravel 預設會使用 function 名稱及對應 table 的 primary key 來組成 foreign key 的名稱,所以在
Car
中,belongsTo
會預設使用 function name 的user
及users
table 的primary key 也就是 id 組成 foreign key:user_id
。
反過來說,如果我們把 foreigin key 放在 users
上,也就是我們在 users
table 上放了 car_id
,那關係就會反過來了。
會變成在 Car
model 中使用 hasOne
去建立跟 User
的關係,而 User
model 則會使用 belongsTo
去和 Car
建立關係。
雖然這個反例在語意上有點怪,不過主要是想說明 hasOne
跟 belongsTo
與 foreigin key 的關係,大家可以根據實際的需求做調整。
結論
hasOne
跟 belongsTo
如何區別?
就結果而言,只要 foreign key
在別人身上,那自己就是使用 hasOne
,若 foregin key
在自己身上,那自己就使用 belongsTo
。
本篇為 PHP 及 Laravel 系列文 → 看更多 PHP 及 Laravel 文章
同場加映:Laravel 一對多關係解釋