igunultas / eager-load-pivot-relations
为Laravel Eloquent的BelongsToMany关系预加载枢纽关系。
v0.2.2
2019-07-26 23:26 UTC
Requires
- php: >=5.6.0
This package is auto-updated.
Last update: 2024-09-27 11:12:56 UTC
README
为Laravel Eloquent的BelongsToMany关系预加载枢纽关系。
Medium故事: https://medium.com/@ajcastro29/laravel-eloquent-eager-load-pivot-relations-dba579f3fd3a
安装
composer require ajcastro/eager-load-pivot-relations
用法和示例
在某些情况下,枢纽模型有需要预加载的关系。例如,在一个采购系统中,我们有以下
表格
items
- id
- name
units
- id
- name (pc, box, etc...)
plans (annual procurement plan)
- id
plan_item (pivot for plans and items)
- id
- plan_id
- item_id
- unit_id
模型
class Unit extends \Eloquent { } use AjCastro\EagerLoadPivotRelations\EagerLoadPivotTrait; class Item extends \Eloquent { // Use the trait here to override eloquent builder. // It is used in this model because it is the relation model defined in // Plan::items() relation. use EagerLoadPivotTrait; public function plans() { return $this->belongsToMany('Plan', 'plan_item'); } } class Plan extends \Eloquent { public function items() { return $this->belongsToMany('Item', 'plan_item') ->using('PlanItem') // make sure to include the necessary foreign key in this case the `unit_id` ->withPivot('unit_id', 'qty', 'price'); } } // Pivot model class PlanItem extends \Illuminate\Database\Eloquent\Relations\Pivot { protected $table = 'plan_item'; public function unit() { return $this->belongsTo('Unit'); } }
从上面的代码中,plans
和items
具有多对多
关系。计划中的每个项目都有一个选定的unit
,即计量单位。枢纽模型也可能在其他场景下有其他多对多关系。
预加载枢纽关系
在预加载枢纽模型时使用关键字pivot
。所以从上面的例子中,枢纽模型PlanItem
可以通过这样做来预加载unit
关系
return Plan::with('items.pivot.unit')->get();
结果的数据结构将是
您也可以访问其他关系,例如
return Plan::with([
'items.pivot.unit',
'items.pivot.unit.someRelation',
'items.pivot.anotherRelation',
// It is also possible to eager load nested pivot models
'items.pivot.unit.someBelongsToManyRelation.pivot.anotherRelationFromAnotherPivot',
])->get();
自定义枢纽访问器
您可以自定义“枢纽访问器”,因此我们不需要使用关键字pivot
,我们可以将其声明为planItem
。只需在BelongsToMany
关系的定义中链式调用as()
方法。
class Plan extends \Eloquent { public function items() { return $this->belongsToMany('Item', 'plan_item') ->withPivot('unit_id', 'qty', 'price') ->using('PlanItem') ->as('planItem'); } }
确保我们也在我们的主要模型(即Plan
模型)上使用这个特性,因为该包需要访问belongsToMany关系(items
关系)以识别使用的枢纽访问器。
use AjCastro\EagerLoadPivotRelations\EagerLoadPivotTrait; class Plan extends \Eloquent { use EagerLoadPivotTrait; }
因此,我们可以通过定义的枢纽访问器planItem
来预加载它,而不是使用pivot
。
return Plan::with('items.planItem.unit')->get();
$plan = Plan::with('items.planItem.unit'); foreach ($plan->items as $item) { $unit = $item->planItem->unit; echo $unit->name; }
其他示例和用例
https://github.com/ajcastro/eager-load-pivot-relations-examples