2023年7月18日

PHP Laravel 小知識:一對多關係 hasMany 跟 belongsTo 解析

之前介紹過 Laravel 的一對一關係 hasOne 跟 belongsTo (這裡),這次要進一步介紹 Laravel Eloquent 用來處理一對多關係的方法:hasMany 跟 belongsTo 。

  • hasMany 指的是「擁有很多東西」。我擁有很多東西,並且我在它們的身上貼上了我的識別代碼。

  • belongsTo 指的是「屬於某個人」。我屬於別人,我被貼上了他的識別代碼。

你沒看錯,belongsTo 重複出現了,至於為什麼,就請接著看下去吧!

範例

我們來看下面的範例,跟之前一樣,假設我們有兩張 Table,分別是 users 及 cars ,在 Laravel 中,分別會對應到 User 及 Car 兩個 Model。

這次跟一對一不一樣的是,我們設定,每個人可以擁有多輛車,每輛車只能被一個人擁有。

也就是一個人對到多台車,一對多關係。

我們將這樣的關係寫成實際的 Laravel 程式,首先是 User Model。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function cars()
    {
        return $this->hasMany(Car::class);
    }
}

在 User Model中,cars method 使用 hasMany:

$this->hasMany(Car::class)

$this 在這邊指的是 User 物件 ,因此這行程式直接讀起來就是:User has many car(s),使用者擁有多輛車,應該還蠻直觀的吧!

再來看 Car Model :

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Car extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

user method 使用 belongsTo :

$this->belongsTo(User::class)

這邊的 $this 就是 Car 物件,整句直接讀是: Car belongs to (a) user,車子屬於一個使用者。

詳細說明

回過頭來確認一次定義:

  • hasMany 指的是「擁有很多東西」。我擁有很多東西,並且我在它們的身上貼上了我的識別代碼。

  • belongsTo 指的是「屬於某個人」。我屬於別人,我被貼上了他的識別代碼。

複習一下,在資料庫中,兩張資料表間的關係,是透過外鍵(foreign key, FK) 來建立的,擁有外鍵的資料表,就像是被貼上了別人的識別代碼,而這個識別代碼通常是所屬者的 primary key, PK 。

為了說明方便,我將擁有 FK 的表稱為子表,相對的,把 PK 放在別人的 FK 中的則是母表。

hasMany

在一對一關係中,母表的 PK 頂多只會出現在子表中一次,不會出現多次,利用這樣的特性來做到一對一關係,這個時候母表的 Model 就可以透過 hasOne 來取出那個唯一一筆。

但在一對多關係中,母表的一個 PK 可以出現在子表中的多筆資料,代表這麼多筆資料都可以對應回同一筆母表資料。這個時候母表的 Model 就可以用 hasMany 來找出子表中的所有的筆數。

belongsTo

前面提過,belongsTo 在一對一關係,及一對多關係的反向關係都重複出現了,其實也很合理,因為一對一的反向,是對回一筆,一對多的反向,也是對回一筆:

  • 一個人有一台車,反之,一台車只會對應一個主人。
  • 一個人有多台車,反之,一台車只會對應一個主人。

因此不論在一對一或一對多關係中,要對應回母表,都可以透過 belongsTo 來對應回去,行為是一樣的。

結論

hasMany 跟 belongsTo 其實不太容易搞混。比較常令人困惑的是為什麼多對一跟一對一的反向關係,都是用 belongsTo 。但其實只要稍微想一下就清楚,其實都是反向對回一筆資料,所以都符合 belongsTo 的行為,這篇就先到這邊啦!謝謝各位閱讀。

本篇為 PHP 及 Laravel 系列文 → 看更多 PHP 及 Laravel 文章