共有4个表:
bundles
:id,name products
:id,name prices
:id,name bundle_product
:id,bundle_id,product_id,price_id 有3种型号:
Bundle
Product
Price
Product
在Price
时有一个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;
但我不想要价格ID ,我想要价格型号。有没有办法从枢轴预加载价格(使用Eager Loading)?
答案 0 :(得分:5)
一种解决方案可能是为枢轴添加BundleProduct
模型。然后将BundleProduct对象链接到Bundle模型:
class Bundle extends Model
{
public function bundleProducts()
{
return $this->hasMany(BundleProduct::class, 'bundle_id', 'id');
}
}
要在此捆绑包中获取所有捆绑包及其相关产品和价格,请执行以下操作:
Bundle::with('bundleProducts.product', 'bundleProducts.price')->get();
这对我有用,希望它可以帮助别人。
答案 1 :(得分:2)
文档:Eloquent: Relationships: Many To Many
默认情况下,只有模型键才会出现在数据透视对象上。如果数据透视表包含额外属性,则必须在定义关系时指定它们:
return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');
这意味着withPivot()
方法只会向pivot
对象添加缺少的字段。要检索实际的Price
模型,您必须建立另一种关系。它看起来像这样:
/**
* Class Bundle
*
* Bundle model with the products relationship
*/
class Bundle extends Model
{
public function products()
{
return $this->belongsToMany(Product::class);
}
}
/**
* Class Product
*
* Product model with the prices relationship
*/
class Product extends Model
{
public function prices()
{
return $this->belongsToMany(Price::class);
}
}
/**
* Class Price
*
* Simple model, end result
*/
class Price extends Model
{
// Model definition...
}
这是基本的,当然不是完整的代码,只有答案所需的功能。
在此之后,您需要做的就是检索关系,如下所示:
// You can query a child relationship using the dot (.). Prices collection will be accessible within each member of the products collection
$all_bundles = Bundle::with('products.prices')->get();
$price_id = $all_bundles->first()
->products->first()
->prices->first()->id;
答案 2 :(得分:2)
我认为你会为一种单独加载价格模型的方法而苦苦挣扎,除非有办法将父母(在这种情况下是产品)传递给一个封闭 - 我和我一样。我很确定没有。
$all_bundles = Bundle::with(['products.prices' => function($query) use (PARENT) {
$query->where('id', PARENT->pivot->price_id);
}])->get();
在初始查询之后,你可以这样做只加载相关的价格模型而不是所有的价格模型:
$all_bundles = Bundle::with('products')->get();
foreach($all_bundles as $bundle) {
foreach($bundle->products as $product) {
$product->load(['prices' => function($query) use ($product) {
$query->where('id', $product->pivot->price_id);
}]);
}
}
答案 3 :(得分:1)
当前接受的答案与原始数据结构不同。 我创建了一个程序包,该程序包可以帮助您实现所需的功能,并且还可以维护原始数据结构。请在此处阅读中等故事: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);
}
}
然后在关系中使用数据透视模型:
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);
}
}
确保在AjCastro\EagerLoadPivotRelations\EagerLoadPivotTrait
模型中使用特征Product
,因为它是belongsToMany关系中的相关模型。这使我们能够急切地加载枢轴关系。
use AjCastro\EagerLoadPivotRelations\EagerLoadPivotTrait;
class Product extends Model
{
use EagerLoadPivotTrait;
}
然后渴望像这样加载它:
$bundle = Bundle::with('products.pivot.price')->first();
$price = $bundle->products->first()->pivot->price;