Since the new ofMany() was added to Laravel I noticed that you can't filter it dynamically as there is no way to append the filter conditions to the inner sub select.
Lets say you have a ofMany:
public function latestDetails(): HasOne
{
return $this->hasOne(UserVesselDetails::class)->latestOfMany('created_at');
}
and you want to filter this down by an id (in my example a vessel_id), you can't. because you either have to add a argument to the relationship - preventing its use in eager loading, or you have to use a static value in it's definition (such as in the doc's example of using now() when defining the relationship)
This does not work (can't eager load it due to the requirement of an parameter):
public function latestDetails(Vessel $vessel): HasOne
{
return $this->hasOne(UserVesselDetails::class)->forVessel($vessel)->latestOfMany('created_at', fn($q) => $q->forVessel($vessel));
}
and neither does this (where does the var come from?):
public function latestDetails(): HasOne
{
return $this->hasOne(UserVesselDetails::class)->where('vessel_id', ????)->latestOfMany('created_at', fn($q) => $q->where('vessel_id', ????));
}
At least for me, this greatly limits the usefulness of this feature
I believe it should be possible to add filtering when modifying the with clause, like you would with any other eager load:
$watches = Watch::with(['user.latestDetails' => fn($q) => $q->forVessel($vessel)])
->forUser($request->user())
->forVessel($vessel)
->get()
The above does not work as expected, as the vessel filter is only applied to the outer select of the ofMany relation, resulting in SQL that does not do as you'd hope:
select
`user_vessel_details`.*
from
`user_vessel_details`
inner join (
select
MAX(`user_vessel_details`.`id`) as `id_aggregate`,
`user_vessel_details`.`user_id`
from
`user_vessel_details`
inner join (
select
MAX(`user_vessel_details`.`created_at`) as `created_at_aggregate`,
`user_vessel_details`.`user_id`
from
`user_vessel_details`
where
`user_vessel_details`.`user_id` in (133)
group by
`user_vessel_details`.`user_id`
) as `latestOfMany` on `latestOfMany`.`created_at_aggregate` = `user_vessel_details`.`created_at`
and `latestOfMany`.`user_id` = `user_vessel_details`.`user_id`
group by
`user_vessel_details`.`user_id`
) as `latestOfMany` on `latestOfMany`.`id_aggregate` = `user_vessel_details`.`id`
and `latestOfMany`.`user_id` = `user_vessel_details`.`user_id`
where
`vessel_id` = 5755
I have not yet found a work around for this, short of not using this feature, building the query myself and using setRelation() :(