Laravel - whereHas checking latest record of a relationship without checking others

后端 未结 4 523
悲哀的现实
悲哀的现实 2020-12-12 01:40

I have two tables that has One to Many relationship.

Bookings - (id)

booking_tasks - (id, booking_id,user_id)

one booking h

4条回答
  •  眼角桃花
    2020-12-12 02:26

    I found the answer from Jonas worked but because it was a query with a join, it caused issues with eager loading relations from the model. So I used that solution with the whereHas function to come up with a solution that could be used in scopes and so would be reusable.

    The first step involves adding a macro to the query Builder in the AppServiceProvider.

    use Illuminate\Database\Query\Builder;
    
    Builder::macro('whereLatestRelation', function ($table, $parentRelatedColumn) 
    {
        return $this->where($table . '.id', function ($sub) use ($table, $parentRelatedColumn) {
            $sub->select('id')
                ->from($table . ' AS other')
                ->whereColumn('other.' . $parentRelatedColumn, $table . '.' . $parentRelatedColumn)
                ->latest()
                ->take(1);
        });
    });
    

    This basically makes the sub-query part of Jonas's answer more generic, allowing you to specify the join table and the column they join on. It assumes the other column is an 'id' column, so it can be improved further. To use this you'd then be able to do:

    $userId = 2;
    Booking::whereHas('tasks', function ($tasks) use ($userId) {
        $tasks->where('user_id', $userId)
            ->whereLatestRelation((new Task)->getTable(), 'booking_id');
    });
    

    It's the same logic as the accepted answer, but a bit easier to re-use. It will, however, be a little slower, but that should be worth the re-usability.

提交回复
热议问题