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及userstable 的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 一對多關係解釋
