Laravel Eloquent : with query parameters
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
# Laravel Eloquent: Mastering Dynamic Query Parameters in Eager Loading
I've finally worked out how to put together a complex query to get related models. The beauty of Eloquent lies in its ability to handle intricate database relationships gracefully through eager loading. However, when you start nesting `with()` clauses and need those constraints to be dynamic—dependent on values from the parent model—you run into a common hurdle: passing variables into nested closures.
This post dives into exactly how to solve that problem efficiently, allowing you to build highly optimized queries without resorting to messy manual joins or subqueries in your application logic.
## The Challenge of Dynamic Scoping in Eloquent
Consider the scenario where you are loading a `Campaign` and need to eager load its related `buyers`, and then for each buyer, you want to load only the `emails` associated with *that specific campaign*.
Your initial attempt looks something like this:
```php
$campaign = Campaign::find($campaign_id);
$buyers = $campaign->buyers()->with('notes')->with(['emails' => function($q){
$q->where('campaign_id', '13'); // Problem: Hardcoded ID!
}])->get();
```
The complexity arises when you try to make the `where` clause inside the closure dynamic. You want `$q->where('campaign_id', $campaign_id)`, but PHP closures often struggle to access variables from the surrounding scope directly without explicit referencing, especially within complex eager loading structures. Hardcoding the ID (`'13'`) defeats the purpose of dynamic querying and leads to incorrect results whenever you load a different campaign.
## The Solution: Capturing Scope with Closures
The solution involves ensuring that the variable `$campaign_id` is accessible within the scope of the closure passed to the `with()` method. While direct access can sometimes be tricky depending on how Eloquent resolves the query builder, the most robust pattern is to leverage PHP's scoping rules or structure the initial query differently.
In this specific case, since you are querying relationships *on* an existing model instance (the `$campaign`), we need to ensure the context of that parent ID is available when building the nested constraints.
Here is the corrected and idiomatic way to achieve dynamic scoping:
```php
$campaign = Campaign::find($campaign_id);
if ($campaign) {
$buyers = $campaign->buyers()
->with('notes') // Eager load notes for buyers
->with(['emails' => function ($query) use ($campaign_id) {
// Now, the closure has access to the outer scope's $campaign_id
$query->where('campaign_id', $campaign_id);
}])
->get();
} else {
$buyers = collect(); // Handle case where campaign is not found
}
```
### Breakdown of the Fix
The key to making this work lies in the `use` keyword within the closure definition: `function ($query) use ($campaign_id)`.
1. **Accessing Outer Variables:** By using `use ($campaign_id)`, we explicitly tell the closure that it needs access to the `$campaign_id` variable defined outside of it (in the main function scope).
2. **Dynamic Constraint:** Inside the closure, we can now safely use this variable: `$query->where('campaign_id', $campaign_id);`. This ensures that every time you iterate through the eager load, the subquery for `emails` is correctly filtered by the specific ID of the parent campaign being loaded.
This technique demonstrates how powerful Eloquent's relationship loading system is, allowing developers to construct complex, multi-level data retrieval using concise syntax. For more advanced database interaction patterns in Laravel, always refer to the official documentation on [laravelcompany.com](https://laravelcompany.com) for the deepest dive into ORM capabilities.
## Conclusion
Mastering dynamic query parameters within Eloquent closures is a significant step toward writing flexible and performant data access layers. By understanding how PHP closures handle scope—specifically by using the `use` keyword to capture parent variables—you can transform