ajcastro / eager-load-pivot-relations
为 Laravel Eloquent 的 BelongsToMany 关系预先加载枢轴关系。
v0.3.0
2022-11-02 13:31 UTC
Requires
- php: >=5.6.0
Requires (Dev)
- laravel/framework: >= 5.0.0
- laravel/legacy-factories: >= 1.0.0
- orchestra/testbench: >= 3.0.0
- phpunit/phpunit: >= 6.0.0
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