Laravel 9如何过滤$with关联查询返回的customerRewards数据?
解决Laravel关联查询中with加载数据的过滤问题
你遇到的问题是whereHas仅筛选出了存在指定客户关联记录的公司,但with('customerRewards')会加载该公司所有的客户奖励记录,不会自动继承whereHas的过滤条件。要同时过滤关联加载的数据,有两种常用方案:
方案一:在with中传入闭包过滤关联数据
直接给with的关联项传递闭包,明确指定关联数据的过滤条件:
use Illuminate\Database\Eloquent\Builder; $companies = Company::with(['customerRewards' => function(Builder $q) use ($customer) { // 过滤关联的customerRewards,仅保留当前客户的记录 $q->where('customer_id', $customer->id); }]) ->has('customerRewards') ->whereHas('customerRewards', function(Builder $q) use ($customer) { $q->where('customer_id', $customer->id); }) ->get();
这样with加载的customerRewards就只会包含指定客户的记录,同时whereHas确保只返回存在该客户关联记录的公司。
方案二:定义带条件的关联关系(适合重复使用场景)
如果这个过滤逻辑需要多次使用,可以在Company模型中定义一个带条件的关联方法:
// Company.php 模型文件 use App\Models\CustomerReward; public function customerRewardsForCustomer($customerId) { return $this->hasMany(CustomerReward::class)->where('customer_id', $customerId); }
然后查询时直接使用这个关联:
$companies = Company::with(['customerRewardsForCustomer' => fn($q) => $q->where('customer_id', $customer->id)]) ->has('customerRewardsForCustomer') ->get();
这个方案让代码更简洁,也便于统一维护过滤逻辑。
内容的提问来源于stack exchange,提问作者Čamo
相关产品推荐
相关产品推荐

