Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

raflisss's avatar

How to load a relation with additional conditional query correctly?

$students = Student::with([
	'user:id,name,image',
	'classGroup' => function (Builder $query) use ($request) {
		$query
			->when($request->query('grade'), function (Builder $query, int $grade) {
				$query->where('grade', $grade);
			})
			->when($request->query('major'), function (Builder $query, string $major) {
				$query->where('major', $major);
      		})
            ->when($request->query('index'), function (Builder $query, string $index) {
                $query->where('index', $index);
             })
             ->select(['id', 'grade', 'major', 'index']);
		},
	])
		->orderByDesc('point')
        ->limit(10)
        ->get(['user_id', 'class_group_id', 'point']);

The code above still loads results for students whose classGroup major is not Science (resulting in classGroup = null) when I submit "major=Science" in the query parameter.

0 likes
6 replies
amitsolanki24_'s avatar
       ->when($request->query('major'), function (Builder $query, string $major) {
			$query->where('major', $major);
           $query->whereNotNull('major');
  		})

Try this or if you can share you major column data it would be helpful

raflisss's avatar

@amitsolanki24_ still doesn't work

  3 => array:5 [▼
    "user_id" => 32
    "class_group_id" => 1
    "point" => 93
    "user" => array:3 [▶]
    "class_group" => array:4 [▼
      "id" => 1
      "grade" => 12
      "major" => "Science"
      "index" => "B"
    ]
  ]
  4 => array:5 [▼
    "user_id" => 15
    "class_group_id" => 3
    "point" => 92
    "user" => array:3 [▶]
    "class_group" => null
  ]

class_group => null because class_group_id => 3 is not Science but Math. I don't know why student with class_group other than Science are still loaded.

amitsolanki24_'s avatar

@raflisss I think at the same time more than 1 when condition is executing, once try to comment other when condition for testing

jaseofspades88's avatar

Assuming student has a lessons relationship. If you wanted to get all the users whose lessons were created after a certain date, you'd be able to do so like this:

User::query()
    ->whereHas('lessons', function(Builder $query) {
		$query->where('created_at', '>=', '2015-01-01 00:00:00');
	})
	->get();
raflisss's avatar

@jaseofspades88

$students = Student::with([
	'user:id,name,image',
 	'classGroup:id,grade,major,index'
])
	->whereHas('classGroup', function (Builder $query) use ($request) {
		$query
        	->when($request->query('grade'), function (Builder $query, int $grade) {
            	$query->where('grade', $grade);
            })
            ->when($request->query('major'), function (Builder $query, string $major) {
                $query->where('major', $major);
            })
            ->when($request->query('index'), function (Builder $query, string $index) {
            	$query->where('index', $index);
            })
            ->select(['id']);
	})
    ->orderByDesc('point')
    ->limit(10)
    ->get(['user_id', 'class_group_id', 'point']);

Yes, it works, thank you. But is that really the way to do it? Because this way is written in the documentation section "Querying Relationship Existence" while the first way is in the section "Constraining Eager Loads" whose description is Sometimes you may wish to eager load a relationship but also specify additional query conditions for the eager loading query. You can accomplish this by passing an array of relationships to the with method where the array key is a relationship name and the array value is a closure that adds additional constraints to the eager loading query fits my case but the results are not as expected.

jaseofspades88's avatar

@raflisss 'Yes it works' - seems to answer that question for you. If you read something in the documentation about doing it better, go with that. Otherwise, choose your best answer and close the thread, kindly.

Please or to participate in this conversation.