Si vous travaillez en chargement différé, ou « lazy loading », les performances pourraient être affectées par le problème de « N+1 requêtes ».
Par exemple, si vous avez 10 catégories et que vous souhaitez exécuter le travail suivant :
$categories = Categorie::all();
foreach ($categories as $categorie) {
echo $categorie->produits->first()->prix;
}
Eloquent effectuera une requête à la base de données pour retrouver la liste des catégories puis il exécutera 10 fois la requête permettant de retrouver le prix d'un produit.
Pour régler ce problème, on pourra forcer le chargement hâtif, ou « eager loading » à l'aide de la méthode with().
La méthode with() prend en paramètre le nom de la méthode définissant la relation (ici : produits()), sans les parenthèses.
$categories = Categorie::with('produits')->get();
foreach ($categories as $categorie) {
echo $categorie->produits->first()->prix;
}
Remarquez que with() reçoit en paramètre le nom d'une propriété dynamique et non le nom d'une table. Donc, pour que ceci fonctionne, le modèle Categorie doit définir une relation portant le nom produits().
Une instruction avec with() réalise deux requêtes SQL. Dans l'exemple précédent :
La syntaxe à utiliser avec findOrFail() est la suivante :
$categorie = Categorie::with('produits')->findOrFail( $id );
La méthode load() permet d'effectuer la seconde requête plus tard. On parlera alors de « lazy eager loading ».
Ceci sera utile, par exemple, si les données de la relation ne sont utiles que dans un contexte donné.
$categories = Categorie::get();
...
if (...) {
$categories->load('produits');
foreach ($categories as $categorie) {
echo $categorie->produits->first()->prix;
}
}
Si vous avez besoin de charger la relation à chaque requête, il est possible d'ajouter une propriété with directement dans le modèle.
La valeur de cette propriété est un tableau qui contient le nom des relations à charger automatiquement.
Ex :
class Categorie extends Model
{
...
/**
* Relations à chargement hâtif automatique (eager load).
*
* @var array
*/
protected $with = ['produits'];
/**
* Une catégorie peut avoir plusieurs produits.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function produits() : HasMany
{
return $this->hasMany('App\Produit');
}
...
}
Le chargement hâtif sera alors automatique avec une requête du genre :
Ex :
$categories = Categorie::get();
Il sera tout de même possible d'effectuer une requête sans charger la relation en utilisant without().
Ex :
$categories = Categorie::without('produits')->get();
« Optimize Eloquent Queries with Eager Loading ». Laravel News. https://laravel-news.com/eloquent-eager-loading
« Laravel Eloquent: Eager Load Pivot Relations ». Medium. https://medium.com/@ajcastro29/laravel-eloquent-eager-load-pivot-relations-dba579f3fd3a
« Finding N+1 Queries in Laravel ». Marcel Pociot. https://pociot.dev/1-finding-n1-queries-in-laravel
▼Publicité