2017-11-19 19 views
1

Ich verstehe nicht wirklich, was ist die Methode von Laravel für eifriges Laden und lösen Sie das Problem der N + 1 Abfrage und was unter der Haube geht. Also habe ich den Test selbst gewählt, um das Ergebnis zu sehen!Eager Ladekonflikt auf Laravel 5.5

So entwarf ich eine einfache Viele-zu-viele-Beziehung, dass jeder tgchannel (Telegrammkanal) viele Tags hat und jedes Tag viele tgchannel hat.

namespace App; 

use Illuminate\Database\Eloquent\Model; 

class tgchannel extends Model 
{  
    public function tags() { 
     return $this->belongsToMany('App\tag'); 
    } 
} 

/////////////////////////////

class tag extends Model 
{ 
    // 
    public function tgchannels() { 
     return $this->belongsToMany('App\tgchannel'); 
    } 

Ich benutzte eager loading Tags zu laden Beziehung in einer Controller-Methode, gemäß Laravel Dokumentation und Ausgang resultierender sql mit dieser Technik:

public function test() 
{ 
    $all_channels = tgchannel::with(['tags'])->toSql(); 
    echo $all_channels.'<br>'; 

    $all_channels = tgchannel::with(['tags'])->get(); 

    foreach ($all_channels as $channel) { 
     $sql = $channel->tags()->toSql(); 
     echo $sql.'<br>'; 
    } 

} 

in der Testdatenbank, musste ich 12 tgchannels, die jeder einen Tag hatten. und schließlich ist dies das Ergebnis:

select * from `tgchannels` 
select * from `tags` inner join `tag_tgchannel` on `tags`.`id` = `tag_tgchannel`.`tag_id` where `tag_tgchannel`.`tgchannel_id` = ? 
select * from `tags` inner join `tag_tgchannel` on `tags`.`id` = `tag_tgchannel`.`tag_id` where `tag_tgchannel`.`tgchannel_id` = ? 
select * from `tags` inner join `tag_tgchannel` on `tags`.`id` = `tag_tgchannel`.`tag_id` where `tag_tgchannel`.`tgchannel_id` = ? 
select * from `tags` inner join `tag_tgchannel` on `tags`.`id` = `tag_tgchannel`.`tag_id` where `tag_tgchannel`.`tgchannel_id` = ? 
select * from `tags` inner join `tag_tgchannel` on `tags`.`id` = `tag_tgchannel`.`tag_id` where `tag_tgchannel`.`tgchannel_id` = ? 
select * from `tags` inner join `tag_tgchannel` on `tags`.`id` = `tag_tgchannel`.`tag_id` where `tag_tgchannel`.`tgchannel_id` = ? 
select * from `tags` inner join `tag_tgchannel` on `tags`.`id` = `tag_tgchannel`.`tag_id` where `tag_tgchannel`.`tgchannel_id` = ? 
select * from `tags` inner join `tag_tgchannel` on `tags`.`id` = `tag_tgchannel`.`tag_id` where `tag_tgchannel`.`tgchannel_id` = ? 
select * from `tags` inner join `tag_tgchannel` on `tags`.`id` = `tag_tgchannel`.`tag_id` where `tag_tgchannel`.`tgchannel_id` = ? 
select * from `tags` inner join `tag_tgchannel` on `tags`.`id` = `tag_tgchannel`.`tag_id` where `tag_tgchannel`.`tgchannel_id` = ? 
select * from `tags` inner join `tag_tgchannel` on `tags`.`id` = `tag_tgchannel`.`tag_id` where `tag_tgchannel`.`tgchannel_id` = ? 
select * from `tags` inner join `tag_tgchannel` on `tags`.`id` = `tag_tgchannel`.`tag_id` where `tag_tgchannel`.`tgchannel_id` = ? 

und Sie können sehen, dass die Abfragen, die ausgeführt sind nicht 2 und N + 1 Abfrage ausgeführt, dass ähnlich wie gemeinsamen verzögertes Laden!

was ist das Problem ??

Antwort

2

Sie erstellen zusätzliche Abfragen statt geladene Daten zu verwenden, so verwenden $channel->tags Sammlung statt $channel->tags():

foreach ($all_channels as $channel) { 
    echo 'Channel: ' . $channel->id . '<br>'; 
    foreach ($channel->tags as $tag) { 
     echo 'Tag: ' . $tag->id . '<br>'; 
    } 
} 
+1

ich gerade, dass man zu schreiben. Er behob das Problem, endete aber immer noch in einer alten Falle. Vote up –

+0

danke für die Antwort, aber warum Ausgang der ersten Abfrage ist "Select * from' tgchannels' "... nichts über die Beziehungen! –