2023年7月18日

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

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

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

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

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

範例

我們來看下面的範例,跟之前一樣,假設我們有兩張 Table,分別是 userscars ,在 Laravel 中,分別會對應到 UserCar 兩個 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 來對應回去,行為是一樣的。

結論

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

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