I have two tables that has One to Many relationship.
Bookings - (id)
booking_tasks - (id, booking_id,user_id)
one booking h
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.