Eloquent eager limit

Voir la vidéo

Dans ce tutoriel je vous propose de découvrir l'extension eloquent eloquent-eager-limit qui permet d'utiliser les fonctions de fenêtrage SQL sur Eloquent.

La problématique

Pour un projet récent on m'a demandé de récupérer les 10 derniers articles avec les derniers commentaires associés pour chacun d'entre eux. La première solution est de récupérer les commentaires dans la boucle de parcourt des éléments

$post->comments()->limit(3)->latest()->get();

Cela génère le problème n+1 et génère 11 requêtes dans notre cas. On pourrait mitiger le problème avec du cache mais cela implique alors de mettre en place une politique d'invalidation du cache qui peut être complexe.

Une autre solution est de récupérer tous les commentaires pour les articles puis de ne lister que les 3 derniers de la collection.

$posts = Post::limit(10)->with('comments')->latest()->get();

Cette approche utilise beaucoup de mémoire en récupérant des commentaires qui ne seront pas utilisés.

La solution

Pour ce genre de problématique il est possible de récupérer les commentaires à l'aide du système de PARTITION.

SELECT * FROM(
    SELECT 
        post_id,
        ROW_NUMBER() OVER (PARTITION BY post_id) as row_number,
        *
    FROM comments
    WHERE post_id IN (7, 6, 5, 4, 3)
) as t
WHERE t.row_number <= 5;

La librairie eloquent-eager-limit va justement permettre de générer ce genre de requête directement depuis Eloquent. Une fois les traits ajoutés à nos models on pourra précharger les relation en ajoutant une limite.

$posts = Post::limit(10)
    ->with([
        'comments' => function ($query) {
            return $query->latest()->limit(3);
        }
    ])
    ->latest()
    ->get();

Maintenant quand on récupèrera les commentaires depuis un article, on aura 3 éléments.

$post->comments // 3 commentaires
Publié
Technologies utilisées
Auteur :
Grafikart
Partager