eloquent - Laravel - Eager Loading Polymorphic Relation's Related Models -
eloquent - Laravel - Eager Loading Polymorphic Relation's Related Models -
i can eager load polymorphic relations/models without n+1 issues. however, if seek access model related polymorphic model, n+1 problem appears , can't seem find fix. here exact setup see locally:
1) db table name/data
history
companies
products
services
2) models
// history class history extends eloquent { protected $table = 'history'; public function historable(){ homecoming $this->morphto(); } } // company class company extends eloquent { protected $table = 'companies'; // each company has many products public function products() { homecoming $this->hasmany('product'); } // each company has many services public function services() { homecoming $this->hasmany('service'); } } // product class product extends eloquent { // each product belongs company public function company() { homecoming $this->belongsto('company'); } public function history() { homecoming $this->morphmany('history', 'historable'); } } // service class service extends eloquent { // each service belongs company public function company() { homecoming $this->belongsto('company'); } public function history() { homecoming $this->morphmany('history', 'historable'); } } 3) routing
route::get('/history', function(){ $histories = history::with('historable')->get(); homecoming view::make('historytemplate', compact('histories')); }); 4) template n+1 logged becacuse of $history->historable->company->name, comment out, n+1 goes away.. need distant related company name:
@foreach($histories $history) <p> <u>{{ $history->historable->company->name }}</u> {{ $history->historable->name }}: {{ $history->historable->status }} </p> @endforeach {{ dd(db::getquerylog()); }} i need able load company names eagerly (in single query) it's related model of polymorphic relation models product , service. i’ve been working on days can't find solution. history::with('historable.company')->get() ignores company in historable.company. efficient solution problem be?
solution:
it possible, if add:
class="lang-php prettyprint-override">protected $with = ['company']; to both service , product models. way, company relation eager-loaded every time service or product loaded, including when loaded via polymorphic relation history.
explanation:
this result in additional 2 queries, 1 service , 1 product, i.e. 1 query each historable_type. total number of queries—regardless of number of results n—goes m+1 (without eager-loading distant company relation) (m*2)+1, m number of models linked polymorphic relation.
optional:
the downside of approach always eager-load company relation on service , product models. may or may not issue, depending on nature of data. if problem, utilize trick automatically eager-load company only when calling polymorphic relation.
add history model:
public function gethistorabletypeattribute($value) { if (is_null($value)) homecoming ($value); homecoming ($value.'withcompany'); } now, when load historable polymorphic relation, eloquent classes servicewithcompany , productwithcompany, rather service or product. then, create classes, , set with within them:
productwithcompany.php
class="lang-php prettyprint-override">class productwithcompany extends product { protected $table = 'products'; protected $with = ['company']; } servicewithcompany.php
class="lang-php prettyprint-override">class servicewithcompany extends service { protected $table = 'services'; protected $with = ['company']; } ...and finally, can remove protected $with = ['company']; base of operations service , product classes.
a bit hacky, should work.
laravel eloquent polymorphic-associations eager-loading polymorphism
Comments
Post a Comment