Tengo las siguientes tablas en mi base de datos:

Me gustaría enumerar los videos con la mejor calificación de comentarios, así:

aplicación/Ayudantes/función.php
function best_comment($data, $value = 'name') { $properties = array(); foreach($data->episodes as $episode) { if(! isset($properties['id']) || $properties['id'] > $season->bestComment[0]->id) { $properties['id'] = $season->bestComment[0]->id; $properties['name'] = $season->bestComment[0]->name; } } if(! empty($properties)) { return $properties[$value]; } }aplicación/Video.php
public function episodes() { return $this->hasMany(Episode::class); }aplicación/Episodio.php
public function bestComment() { return $this->belongsToMany(Rating::class, 'comments', 'id')->orderBy('id', 'asc')->limit(1); }app/Http/Controllers/VideosController.php
public function index() { $videos = Videos::query(); $videos->with('episodes'); return view('videos.index')->with('videos', $videos->paginate(4)); }recursos/vistas/videos/index.blade.php
@foreach($videos as $video) <div> <h5>{{ $video->title }}</h5> Best comment rating: {{ best_comment($video, 'name') }} </div> @endforeachCon mi solución hay muchas consultas. ¿Cuál es la mejor manera de imprimir el comentario mejor valorado?
Esta no es la solución más óptima, pero debería funcionar.
Primero obtenga las ID de los modelos de Video del objeto de paginación:
$ids = $videos->getCollection()->pluck('id');
Luego, úselos para unirse a las otras tablas, agrupándolos por video y eligiendo el ID de calificación más alto. Es posible que deba modificar esto si tiene otras columnas en su tabla de calificación, es decir, para que pueda clasificarlas mejor que usar su clave principal.
$videoToRatingMap = Videos::query() ->whereIn('id', $ids) ->join('episodes', 'episodes.video_id', '=', 'videos.id') ->join('comments', 'comments.episode_id ', '=', 'episodes.id') ->join('ratings', 'ratings.id', '=', 'comments.rating_id') ->groupBy('videos.id') ->select('videos.id') ->selectRaw('max(ratings.id) as rating_id') ->get();Esto le dará un mapa de los videos por ID y el comentario mejor clasificado.
Sin embargo, esto no le dará los nombres de las clasificaciones, eso se puede hacer en una consulta separada:
$ratingNames = Rating::query() ->findMany($videoToRatingMap->pluck('rating_id')) ->pluck('name', 'id');Luego transforme el mapa de calificación para incluir los nombres:
$videoToRatingMap->transform(function($video) use ($ratingNames){ $video['rating_name'] = $ratingNames[$video['rating_id']]; return $video; })->keyBy('id');Esto le dará una colección, codificada por las ID de video que también contiene la ID de calificación y su nombre.
Una forma un poco más óptima de hacer esto es tomar la primera consulta y envolver todo en una subconsulta, de esa manera podría unirse a la tabla de calificaciones nuevamente y obtener el nombre. Reduciría las consultas en una a costa de hacer que la consulta única sea más compleja.