Lumethys's avatar

Eloquent: Where Relationship as subquery

Recently i encounter a problem that eloquent seems to have to built-in solution. And I would be very appreciated if I could get some help

Consider this simplified relationship:

Path - one to many - Segment
Segment - Many to Many - Checkpoint

a Path will have many Segment, each Segment may or may not pass some Checkpoint

so

path1 [
	seg1, 
	seg2,
	seg3,
]
path2[
	seg1[check1, check2],
	seg2[check2, check3],
	seg3
]

i want to query all Path (and related Segments) that had Segments after Checkpoint had some specific status

something akin to this:

Path::withWhereHas('segments', function (Builder $query) {
	$query->where('segment_number', '>=',  $lastSegmentThatPassedACheckpoint)
		->whereIn('status', [1,2,3])
})

the "last segment that passed a checkpoint" bit seem easy, it's just segments->has('checkpoints')->orderByDesc('segment_number')->first()->segment_number, but i cant run it as a separate query because i'm query a list and each path will have different "last segment that passed checkpoint". Which mean i need to run it as a subquery

which is something like this:

Path::withWhereHas('segments', function (Builder $query) {
	$query->where('segment_number', '>=',  function (Builder $query){
		$query->select('segment_number')->whereHas('checkpoint')->orderByDesc('segment_number')->limit(1)
	})
	->whereIn('status', [1,2,3])
})

but the whereHas bit wont work, because the second subquery is a new database builder, not an eloquent builder with the 'segment' relation like the first subquery

i tried to build the whereHas part from scratch, whereExist ( select ... inner join ... where ...), but unfortunately, it require the current path.id in question ->whereColumn('segments.path_id', 'path.id'), which doesnt exist when eloquent ran a second query to eager load the segments (withWhereHas)

0 likes
1 reply
Thunderson's avatar

Show me please each property of models and which data do you want to have at the end.

Please or to participate in this conversation.