渴望加载:在具有雄辩关系的枢轴上使用`with`

rap*_*2-h 7 php laravel eloquent laravel-5

有4个表:

  • bundles:ID,名称
  • products:ID,名称
  • prices:ID,名称
  • bundle_product:id,bundle_id,product_id,price_id

有3种型号:

  • Bundle
  • Product
  • Price

A中Product有一个Pricewhen Bundle。我想拥有所有bundles与它们相关联的products 和关联的prices我可以获取所有捆绑销售的产品及其价格ID:

// I created a Bundle Model with a products method
class Bundle extends Model
{
    public function products()
    {
        return $this->belongsToMany(Product::class)->withPivot('price_id');
    }
}

// Then I call this in a controller
$all_bundles = Bundle::with('products')->get();

// Then I can get the price Id of the first product of the first bundle
$price_id = Bundle::with('products')->first()
    ->products()->first()
    ->pivot->price_id;
Run Code Online (Sandbox Code Playgroud)

但是我不想要价格id,我想要价格模型。有什么办法可以从数据透视图中预加载价格(使用“急切加载”)?

小智 14

当前接受的答案偏离了原始数据结构。我创建了一个包,它可以帮助你实现你想要的,并且它维护了原始数据结构。请在这里阅读我的媒体故事:https : //medium.com/@ajcastro29/laravel-eloquent-eager-load-pivot-relations-dba579f3fd3a

首先,创建您的自定义枢轴模型并在枢轴模型上定义关系,在您的情况下:

use Illuminate\Database\Eloquent\Relations\Pivot;

class BundleProduct extends Pivot
{
    public function price()
    {
        return $this->belongsTo(Price::class);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在关系中使用枢轴模型:

class Bundle extends Model
{
    public function products()
    {
        return $this->belongsToMany(Product::class)
        ->withPivot('price_id') // this is needed to query the relation `price`
        ->using(BundleProduct::class);
    }
}
Run Code Online (Sandbox Code Playgroud)

确保AjCastro\EagerLoadPivotRelations\EagerLoadPivotTraitProduct模型中使用特征,因为它是belongsToMany 关系中的相关模型。这让我们能够预先加载枢轴关系。

use AjCastro\EagerLoadPivotRelations\EagerLoadPivotTrait;

class Product extends Model 
{
  use EagerLoadPivotTrait;
}
Run Code Online (Sandbox Code Playgroud)

然后像这样急切加载它:

$bundle = Bundle::with('products.pivot.price')->first();
$price = $bundle->products->first()->pivot->price;
Run Code Online (Sandbox Code Playgroud)


rap*_*2-h 7

一种解决方案是BundleProduct为枢轴添加模型。然后将BundleProduct对象链接到Bundle模型:

class Bundle extends Model
{
    public function bundleProducts()
    {
        return $this->hasMany(BundleProduct::class, 'bundle_id', 'id');
    }
}
Run Code Online (Sandbox Code Playgroud)

要获取捆绑中所有捆绑包及其相关产品和价格,只需执行以下操作:

Bundle::with('bundleProducts.product', 'bundleProducts.price')->get();
Run Code Online (Sandbox Code Playgroud)

那对我有用,希望它能对其他人有所帮助。