gpt4 book ai didi

Laravel - 渴望加载多态关系的相关模型

转载 作者:行者123 更新时间:2023-12-03 01:43:15 25 4
gpt4 key购买 nike

我可以立即加载多态关系/模型,而不会出现任何 n+1 问题。但是,如果我尝试访问与多态模型相关的模型,则会出现 n+1 问题,并且我似乎无法找到解决方案。以下是在本地查看它的确切设置:

1) 数据库表名称/数据

历史

history table

公司

enter image description here

产品

enter image description here

服务

enter image description here

2) 模型

// History
class History extends Eloquent {
protected $table = 'history';

public function historable(){
return $this->morphTo();
}
}

// Company
class Company extends Eloquent {
protected $table = 'companies';

// each company has many products
public function products() {
return $this->hasMany('Product');
}

// each company has many services
public function services() {
return $this->hasMany('Service');
}
}

// Product
class Product extends Eloquent {
// each product belongs to a company
public function company() {
return $this->belongsTo('Company');
}

public function history() {
return $this->morphMany('History', 'historable');
}
}

// Service
class Service extends Eloquent {
// each service belongs to a company
public function company() {
return $this->belongsTo('Company');
}

public function history() {
return $this->morphMany('History', 'historable');
}
}

3) 路由

Route::get('/history', function(){
$histories = History::with('historable')->get();
return View::make('historyTemplate', compact('histories'));
});

4) 仅因为 $history->historable->company->name 才记录 n+1 的模板,将其注释掉,n+1 消失..但我们需要那个遥远的相关公司名称:

@foreach($histories as $history)
<p>
<u>{{ $history->historable->company->name }}</u>
{{ $history->historable->name }}: {{ $history->historable->status }}
</p>
@endforeach
{{ dd(DB::getQueryLog()); }}

我需要能够立即加载公司名称(在单个查询中),因为它是多态关系模型 ProductService 的相关模型。我已经为此工作了好几天,但找不到解决方案。History::with('historable.company')->get() 只是忽略 historable.company 中的 company。这个问题的有效解决方案是什么?

最佳答案

解决方案:

这是可能的,如果你添加:

protected $with = ['company']; 

ServiceProduct楷模。这样,company每次 Service 时都会急切加载关系或Product被加载,包括通过 History 的多态关系加载时。

<小时/>

说明:

这将导致额外的 2 个查询,其中一个针对 Service和一个 Product ,即每个 historable_type 一个查询。因此,无论结果数量有多少,您的查询总数 n —来自m+1 (无需急切加载远程 company 关系)到 (m*2)+1 ,其中m是通过多态关系链接的模型数量。

<小时/>

可选:

这种方法的缺点是您总是急切加载 company关系 ServiceProduct楷模。这可能是也可能不是问题,具体取决于数据的性质。如果这是一个问题,您可以使用此技巧自动急切加载 company 在调用多态关系时。

将此添加到您的 History型号:

public function getHistorableTypeAttribute($value)
{
if (is_null($value)) return ($value);
return ($value.'WithCompany');
}

现在,当您加载historable时多态关系,Eloquent 会寻找类 ServiceWithCompanyProductWithCompany ,而不是 ServiceProduct 。然后,创建这些类,并设置 with在它们里面:

ProductWithCompany.php

class ProductWithCompany extends Product {
protected $table = 'products';
protected $with = ['company'];
}

ServiceWithCompany.php

class ServiceWithCompany extends Service {
protected $table = 'services';
protected $with = ['company'];
}

...最后,您可以删除 protected $with = ['company'];从基地ServiceProduct类。

有点hacky,但应该可以。

关于Laravel - 渴望加载多态关系的相关模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26727088/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com