Laravel Eloquent关联中where子句使用及未定义变量问题排查
Hey there! Let's tackle your two issues step by step—first the "undefined variable" error, then how to properly use where clauses in Eloquent relationships.
1. Fixing the "Undefined Variable" Error
Looking at your controller code, the problem is that the closure you passed to with() can't access the $request variable from the outer scope by default. Closures in PHP have their own isolated scope, so you need to explicitly pass variables into them using the use keyword.
Here's the corrected version of your controller code:
$assignedCases = AddressCaseAssign::with(['addresses' => function ($query) use ($request) { // Now $request is accessible inside the closure $query->where('company_id', '=', $request->company); }])->where('user_id', $request->executive)->get();
Alternatively, you can extract the company value first to make the code cleaner:
$companyId = $request->company; $assignedCases = AddressCaseAssign::with(['addresses' => function ($query) use ($companyId) { $query->where('company_id', $companyId); }])->where('user_id', $request->executive)->get();
This tells PHP to bring the $request (or $companyId) variable into the closure's scope, so it won't throw the "undefined variable" error anymore.
2. Using Where Clauses in Eloquent Relationships
There are a few common ways to apply where clauses to Eloquent relationships—let's cover the ones relevant to your use case:
a. Filtering Eager Loaded Relationships (What You're Doing)
The with() method with a closure lets you filter the related data that gets eager loaded. This means you'll get all AddressCaseAssign records where user_id matches $request->executive, but only the addresses related to those records that have a matching company_id will be loaded.
b. Filtering Parent Records by Related Data
If you want to only get AddressCaseAssign records that have an associated address with the correct company_id (instead of just filtering the loaded addresses), use whereHas():
$assignedCases = AddressCaseAssign::whereHas('addresses', function ($query) use ($request) { $query->where('company_id', $request->company); })->where('user_id', $request->executive)->get();
This will return only the AddressCaseAssign records that have at least one address matching the company_id condition—no empty addresses relationships here.
c. Adding Global Constraints to the Relationship
If you want the addresses relationship to always apply a where clause (every time you access it), you can define it directly in the model:
public function addresses() { // Replace 'some_company_id' with your fixed value or dynamic logic return $this->belongsTo(Address::class, 'address_id')->where('company_id', '=', 'some_company_id'); }
This is useful for permanent constraints, but keep in mind it will apply to every query using this relationship.
内容的提问来源于stack exchange,提问作者Sandeep

