I can eager load polymorphic relations/models without any n+1 issues. However, if I try to access a model related to the polymorphic model, the n+1 problem appears and I can't seem to find a fix. Here is the exact setup to see it locally:
1) DB table name/data
history
companies
products
services
2) Models
// 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) Routing
Route::get('/history', function(){
$histories = History::with('historable')->get();
return View::make('historyTemplate', compact('histories'));
});
4) Template with n+1 logged only becacuse of $history->historable->company->name, comment it out, n+1 goes away.. but we need that distant related company name:
@foreach($histories as $history)
<p>
<u>{{ $history->historable->company->name }}</u>
{{ $history->historable->name }}: {{ $history->historable->status }}
</p>
@endforeach
{{ dd(DB::getQueryLog()); }}
I need to be able to load the company names eagerly (in a single query) as it's a related model of the polymorphic relation models Product
and Service
.
I’ve been working on this for days but can't find a solution.
History::with('historable.company')->get()
just ignores the company
in historable.company
.
What would an efficient solution to this problem be?
Company
model dynamically by$historables->load('company')
– KovacevCompany
? – Foothold