audunru / eager-load-pivot-relations
为 Laravel Eloquent 的 BelongsToMany 关系预加载枢纽关系。
Requires
- php: ^8.2
- illuminate/database: ^11.0
- illuminate/support: ^11.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- orchestra/testbench: ^9.0
- php-coveralls/php-coveralls: ^2.2
- phpmd/phpmd: ^2.10
- phpunit/phpunit: ^11.0
- roave/security-advisories: dev-latest
This package is auto-updated.
Last update: 2024-09-25 07:34:32 UTC
README
注意:这是一个基于 ajcastro/eager-load-pivot-relations 的分支,支持 Laravel 8 及以上版本,也由 ajcastro 编码。感谢原作者为这个包及其工作所做的贡献。
为 Laravel Eloquent 的 BelongsToMany 关系预加载枢纽关系。
Medium 故事: https://medium.com/@ajcastro29/laravel-eloquent-eager-load-pivot-relations-dba579f3fd3a
安装
composer require audunru/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 audunru\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 audunru\EagerLoadPivotRelations\EagerLoadPivotTrait; class Plan extends \Eloquent { use EagerLoadPivotTrait; }
因此,我们不必使用 pivot
,而可以通过定义的枢纽访问器 planItem
预加载它。
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