我有两个模型。Product
和Vendor
。这些模型有多对多的关系。透视表有额外的列旁边product_id
和vendor_id
,price and off_price
所以表列如下:
| 产品标识|供应商标识|价格|减价|
| - ------|- ------|- ------|- ------|
我在Product
模型中编写了自定义属性:
protected $appends = [
'cheapest_vendor'
];
protected function CheapestVendor(): Attribute
{
$price = $this->belongsToMany(Vendor::class)->min('price');
$vendor = $this->belongsToMany(Vendor::class)->where('price', '=', $price)->first();
return new Attribute(
get: fn () => ['price' => $price, 'vendor' => $vendor],
);
}
在我的刀锋档案里
$product->cheapest_vendor->price and $product->cheapest_vendor->vendor->name
多次。问题是我有这么多的重复查询的刀片式服务器页,因为这一点。我知道每次我调用cheapest_vendor
属性,我实际上运行2查询,但我想不出其他方法来做到这一点。我需要一种方法来找到最低价格的透视表和供应商的产品没有这么多的重复查询。
1条答案
按热度按时间11dmarpk1#
您的问题肯定是在Attribute方法中同时包含
$price = $this->belongsToMany(Vendor::class)
和$vendor = $this->belongsToMany(Vendor::class)
。如果您在那里定义它们,则无法检查该Relationship是否已加载,因此每次访问$product->cheapest_vendor
时都将调用2 Queries。您 * 可以 * 通过与
vendors
的单个关系来完成此操作:下一步分为两部分:
1.确保“属性”检查加载的关系并使用它(如果已定义)或加载它:
对于单个模型,这非常有效。您可以这样做:
并且只会调用一个额外的查询。
1.对于多个模型,请确保在继续之前正确加载关系:
现在,当循环这些产品并显示其
cheapest_vendor
属性时,将不执行任何其他查询:如果拥有2个关系(1个与
vendors
,一个与cheapest_vendors
)更容易,您也可以这样做:belongsToMany()
,因为它们通过pivot
表连接 *现在,您可以简化您的逻辑:
加载
$product
(或$products
)时,在控制器中:当访问
$product->cheapest_vendor->price
(和->vendor->name
)时,将不执行任何其他查询。这还允许您访问->vendors
,它将返回所有关联的供应商,而在单一关系方法中,->vendors
将仅包括单个Vendor
模型示例的集合。