Skip to main content

什麼是關聯

資料庫的資料表之間常有關聯關係。例如,一篇部落格文章可能有多則評論,或訂單會與下單的使用者相關聯。 Eloquent 為這些資料表間的關聯提供了簡單的定義與操作方式。關聯是定義為 Eloquent 模型上的方法。
本頁使用 UserPostCommentTag 等具體模型作為範例。 假設這些模型與資料表已建立好。
Eloquent 支援的主要關聯如下:

hasOne(一對一)

hasOne 代表某模型只擁有另一個模型的一筆。例如 User 擁有一個 Profile

定義關聯

User 模型中定義 profile 方法。
Eloquent 會根據父模型名稱推測外鍵。這個例子會預設 profiles 資料表有 user_id 欄位。

取得關聯資料

已定義的關聯可以以屬性方式存取。
以屬性方式呼叫關聯方法時,Eloquent 會自動發送查詢並回傳關聯資料。這稱為「動態關聯屬性」。

belongsTo(一對一反向)

belongsTohasOne 的反向,定義在擁有外鍵一側的模型。表達 Profile 屬於 User 的關係。

定義關聯

Eloquent 會使用關聯方法名稱後加 _id(此例中 user_id)作為外鍵。

取得關聯資料

hasMany(一對多)

hasMany 是最常使用的關聯,代表一個父模型擁有多個子模型。例如 Post 有多個 Comment

定義關聯

Eloquent 會預設 comments 資料表有 post_id 欄位。

取得關聯資料

hasMany 關聯會回傳集合。
也能在查詢中加入條件。

反向關聯(belongsTo)

要從評論參照文章,可在 Comment 模型中定義 belongsTo

belongsToMany(多對多)

多對多關聯用於兩方模型互相擁有多個關聯的情境。例如 Post 有多個 Tag,而 Tag 也屬於多個 Post

資料表結構

多對多需要中介資料表。PostTag 的例子中會準備一張叫做 post_tag 的中介資料表。
中介資料表名稱由 Eloquent 依關聯的兩個模型名稱按字母順序合併推測(post + tagpost_tag)。

定義關聯

Tag 這邊也定義同樣的方法,就能從反方向也存取。

取得關聯資料

新增 / 移除關聯資料

attach 新增中介資料表紀錄,detach 刪除。
使用 sync 會自動刪除中介資料表中不屬於指定 ID 的紀錄,僅保留你傳入的 ID 作為關聯。

Eager Loading

什麼是 N+1 問題

以屬性方式存取關聯時,Eloquent 會每次都執行查詢。這稱為「延遲載入(Lazy Loading)」。在迴圈中存取關聯會發生 N+1 問題。
若文章有 100 篇,就會執行 101 次查詢,對效能影響非常大。

用 with() 進行 Eager Loading

透過 with() 方法可以一起取得關聯資料,將查詢降到 2 次。
實際執行的 SQL 只有以下 2 個:

一次 Eager Load 多個關聯

可用陣列指定多個關聯。

巢狀的 Eager Loading

以點記號可 Eager Load 巢狀關聯。
Eager Loading 對避免 N+1 問題非常重要。當在迴圈中存取關聯時,請養成使用 with() 的習慣。

下一步

Eloquent 入門

回頭複習 Eloquent 的基本 CRUD 操作。
最後修改於 2026年8月2日