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日