Skip to main content

什麼是自訂 Pivot Model

belongsToMany(多對多)的中介資料表,預設會以未加工的 Illuminate\Database\Eloquent\Relations\Pivot 實例處理。若想在中介資料表加入額外欄位(例如審核時間、角色種類等),或想新增 accessor、mutator、自訂方法時,可以建立繼承 Pivot 的自訂 Model。
在 belongsToMany 的定義中呼叫 using(),告訴關聯改用這個自訂 Model。
儲存自訂 Pivot Model 時,Model 名稱請務必採用 字母順序的單數形式 命名(也就是 RoleUser,而不是 UserRole)。不過這只是命名慣例,實際的類別名稱可以自由決定。

以 as() 指定想取得的屬性

預設情況下,中介資料表的值透過 pivot 屬性存取。使用 as() 方法可以變更此名稱。

額外欄位與 timestamp

若中介資料表有 approved 這類額外欄位,需以 withPivot() 明確納入取得對象。若要管理 created_at / updated_at,請呼叫 withTimestamps()。
只有在以 using() 明確指定 Pivot Model 時,Eloquent 才會自動更新中介資料表的 updated_at。即使沿用預設的 Pivot 類別,withTimestamps() 仍然可以運作,但以 using() 指定自訂 Model 後,就可以使用自訂事件、自訂 cast 等功能。

從 Pivot Model 反向參照

自訂 Pivot Model 上可以自由定義指向宣告端 Model 與關聯端 Model 的 belongsTo 關聯。
如此一來,即使只取得 Pivot Model 本身,也能透過 $roleUser->role、$roleUser->user 存取關聯 Model。不過若希望在父查詢執行時自動 Eager Load 這些關聯,可以使用下一節介紹的 chaperone()。

以 chaperone() 進行自動 Eager Loading(Laravel 13)

Laravel 13 新增了 chaperone() 方法,可將 Pivot Model 上定義的 role() / user() 等 belongsTo 關聯,於 belongsToMany 查詢執行時自動 hydrate(等同 Eager Load 的連結)。
呼叫 chaperone() 後,Eloquent 會自動推測 Pivot Model(RoleUser)所持有的 belongsTo 關聯名稱;在以 Role::with('users') 等方式取得集合時,會為每個 pivot 設定指向宣告端 Model 與關聯端 Model 的參照,且不需要額外的查詢。

使用非標準的關聯名稱時

若 Pivot Model 上 belongsTo 關聯的方法名稱與標準命名(宣告端/關聯端 Model 名稱的 camelCase 單數形)不同,可以透過 chaperone() 的參數明確指定。
chaperone() 是可以連中介資料表相關參照也一併解決「N+1 問題」的機制。在頻繁從 Pivot Model 參照父 Model 資訊(如同時顯示審核時間與使用者名稱)的應用中,搭配一般的 with() Eager Load 使用,效果非常好。

下一步

關聯

回頭複習包含 belongsToMany 在內的基本關聯定義方式。

Eloquent Observers 與 Model 事件

學習如何以 Model 事件 hook Pivot Model 的儲存、更新。
最後修改於 2026年9月11日