Sélectionner la première ligne de chaque occurence avec with() Query Builder
Bonjour,
J'apprends actuellement à développer avec Laravel et j'ai un soucis au niveau d'une requête SQL (avec query builder) que je n'arrive pas à réaliser. Je réalise un view composer pour générer une requête SQL qui doit récupérer la progression du dernier épisode des séries en cours, en pause ou planifiées (je possède une table avec l'ensemble des séries, et une autre avec les épisodes liées avec une relation 1:n).
Ma requête récupère bien les séries, mais pour les épisodes je cherche à récupérer uniquement le dernier de chaque série pour avoir son avancement. Sauf que la méthode first() ne va récupérer que le dernier épisode de la 1ere série et non le dernier épisode de chaque série.
Auriez-vous une idée de comment je devrais procéder ?
J'ai cherché quelques solutions dont limit(1), first(), take(1), mais en vain... Merci d'avance !
Voici mon fichier view composer avec ma requête
<?php
namespace App\Http\ViewComposers;
use Illuminate\View\View;
use App\ {
Models\Series,
Models\Episode
};
class SidebarComposer
{
public function compose(View $view) {
$view->with('progress', Series::select('id', 'name', 'status', 'slug', 'progress_color', 'progress_display')
->where('status', 'In Progress')
->orWhere('status', 'Paused')
->orWhere('status', 'Planed')
->where('progress_display', 1)
->with([
'episodes' => function ($q) {
$q->select('id', 'series_id', 'num', 'progress')->orderBy('num', 'DESC')->first();
}
])
->get()
);
}
}
Pour les personnes qui se posent la question, progressdisplay est un boolean qui permet de dire s'il faut afficher ou non la série dans le tableau de progression que je rend disponible sur chaque page
Salut,
As tu essayé avec :
->latest()->first()
ou
->last()
?
Salut !
Oui, latest ne fonctionne pas car il faut enregistrer la date de création en BDD (created_at), ce que je n'ai pas.
Quant à last il n'a pas l'air de connaître :
Call to undefined method Illuminate\Database\Eloquent\Relations\HasMany::last()
Re,
J'ai fini par trouver une solution grâce à cet article : https://www.laravelcode.com/post/how-to-get-last-record-from-leftjoin-table-in-laravel
$view->with('progress', Series::select('series.name', 'series.status', 'series.slug', 'series.progress_color', 'series.progress_display', 'episodes.num', 'episodes.progress')
->leftJoin('episodes', function($query) {
$query->on('episodes.series_id','=','series.id')
->whereRaw('episodes.id IN (select MAX(a2.id) from episodes as a2 join series as u2 on u2.id = a2.series_id group by u2.id)');
})
->where('series.status', 'In Progress')
->orWhere('series.status', 'Paused')
->orWhere('series.status', 'Planed')
->where('series.progress_display', 1)
->get()
);
A ma connaissance, il n'y a pas moyen de simplifier ça mais si quelqu'un a une solution plus simple je suis preneur ;)
Belle requête !!
Vous ne pouvez pas répondre à ce sujet.