Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

318
Views
What's the best way to get a row through a table in Laravel?

I have the following tables in my database:
Database relationship

I would like to list videos with the best rating of comments, like this:
List database content

app/Helpers/function.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];
    }
}

app/Video.php

public function episodes() {
    return $this->hasMany(Episode::class);
}

app/Episode.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));
}

resources/views/videos/index.blade.php

@foreach($videos as $video)
    <div>
        <h5>{{ $video->title }}</h5>
        Best comment rating: {{ best_comment($video, 'name') }}
    </div>
@endforeach

With my solution there are many queries. What's the best way to print the best rated comment?

Laravel Sandbox

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

This is not the most optimal solution, but it should work.

First get the IDs of the Video models from the pagination object:

$ids = $videos->getCollection()->pluck('id');

Then use those to join the other tables, grouping by video and picking the highest rating ID. You might need to tweak this if you have other columns on your rating table, i.e. so you can rank them better than using their primary key.

$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();

This will get you a map of the Videos by ID and the highest ranked comment.

This won't get you the names of the rankings however, that can be done in a separate query:

$ratingNames = Rating::query()
    ->findMany($videoToRatingMap->pluck('rating_id'))
    ->pluck('name', 'id');

Then transform the rating map to include the names:

$videoToRatingMap->transform(function($video) use ($ratingNames){
    $video['rating_name'] = $ratingNames[$video['rating_id']];
    return $video;
})->keyBy('id');

This will give you a collection, keyed by the Video IDs that also contains the rating ID and its name.

A slightly more optimal way to do this is to take the first query and wrap the whole thing into a subquery, that way you could join the ratings table on it again and get the name. Would reduce the queries by one at the cost of making the single query more complex.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!