When accessing Eloquent relationships as properties, the data in the relationship is "lazy loaded" or known as lazy loading.
This means that the relationship data is not actually loaded until the property is first accessed.
However, Eloquent can "eager loading" relationships at the time it queries the parent model. Eager loading alleviates the problem of N+1 queries.
To illustrate the N + 1 query problem, consider the following models:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\URL;
class Tutorial extends Model
{
use HasFactory;
protected $fillable = [***];
public function sections()
{
return $this->hasMany(TutorialSection::class)->orderBy('orden');
}
}
class TutorialSection extends Model
{
use HasFactory;
protected $fillable = [***];
public function tutorial()
{
return $this->belongsTo(Tutorial::class);
}
public function classes()
{
return $this->hasMany(TutorialSectionClass::class)->orderBy('orden');
}
}
class TutorialSectionClass extends Model
{
use HasFactory;
protected $fillable = [***];
public function tutorialSection()
{
return $this->belongsTo(TutorialSection::class);
}
public function comments()
{
return $this->hasMany(TutorialSectionClassComment::class);
}
}
The query of:
$tutorials = Tutorial->get();
foreach ($tutorials as $key => $t)
foreach ($t->sections as $key => $s)
It will execute a query to retrieve all the tutorials:
$tutorials = Tutorial->get();
Then, we iterate all the tutorials and, in turn, we obtain the sections for each tutorial; if we have 25 tutorials, it would be an additional query to the database for each tutorial to get the sections; It would be 26 queries, 1 for the tutorial with the sections and 25 more for each section; here we have the problem known as N+1 since, depending on the number of tutorials we have, we have to make the same number of queries to the database to obtain its sections; but, things can get more complicated; if now, let's get the classes:
then if we want to get the classes:
foreach ($s->classes->get() as $k => $c)
The result would be catastrophic; fortunately, in Laravel we can solve this problem so that it returns a single query to the database.
Eager Loading
In Laravel, Eager Loading is an optimization technique to reduce the number of queries to the database. By default, when retrieving data with relationships in Laravel, Lazy Loading is used, which can result in the N+1 query problem as explained above.
Eager Loading is a data loading technique in which related data is loaded in advance to avoid the need to load it later when it is accessed in a single query, therefore this technique solves the previous N+1 problem; To do this, we must use the with function indicating the name of the relationship in the model:
$tutorial = Tutorial::with('sections');
Eager Loading Multiple Relationships
If we want to place additional relations, we can specify them in an array; if the relations are nested, we can do the following:
$tutorial = Tutorial::with(['sections','sections.classes' ])
As you can see, we put the first relation:
sections
And then the innermost relationship:
sections.classes
Eager Loading conditions
Many times it is necessary to indicate additional conditions, for this, we can specify a callback function in which we place the internal conditions, in the following example, we want the classes to be posted or published:
$tutorial = Tutorial::with('sections')->with(['sections.classes' => function ($query) {
$query->where('posted', 'yes');
}])->find($tutorial->id);
And with this, you can easily create your relationships at the time of loading the parent relationship; this is particularly useful when you need to build a Rest API and you initially need all the data, including the parent and child relationship.
Define the Eager Loading directly in the models
In the models, we can default to the use of eager loading as we saw previously; to do this, we use the with property:
class Tutorial extends Model
{
***
protected $with = ['sections'];
}
- Andrés Cruz
![Andrés Cruz Andrés Cruz](/public/images/perfil.jpg)
Develop with Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter