Laravel中第二个参数为带LIKE的闭包时两个关联仅其一生效问题
Laravel关联查询带LIKE闭包仅生效一个的解决方案
嘿,这个问题我之前在项目里实打实碰到过,大概率是变量作用域遗漏或者查询逻辑写法错误导致的,我来给你拆解下解决思路:
先排查最常见的坑:变量未传入闭包
很多时候出现这种情况,是因为你在闭包里用$term时,没通过use($term)把外部变量传入闭包,导致其中一个关联查询的LIKE条件根本没拿到正确的搜索关键词,相当于白写了。
举个正确的写法例子(假设你要关联查询Driver和Maintenance两个模型,用$term过滤它们的字段):
$term = "你的搜索关键词"; $vehicles = Vehicle::query() // 第一个关联查询:过滤Driver的name字段 ->whereHas('driver', function ($query) use ($term) { $query->where('name', 'LIKE', "%{$term}%"); }) // 第二个关联查询:过滤Maintenance的description字段 ->whereHas('maintenance', function ($query) use ($term) { $query->where('description', 'LIKE', "%{$term}%"); }) ->get();
注意每个闭包后面都加了use($term),这是Laravel闭包查询传递外部变量的关键,少了它,闭包里的$term就是未定义的,对应的LIKE条件要么变成空匹配,要么直接不生效。
检查查询逻辑是“且”还是“或”
如果你需要的是满足任意一个关联条件就返回结果,那不能连续用whereHas,得换成orWhereHas——不然两个条件是“且”的关系,可能因为其中一个关联的数据不存在,导致所有结果被过滤,看起来像只有一个条件生效:
$vehicles = Vehicle::query() ->whereHas('driver', function ($query) use ($term) { $query->where('name', 'LIKE', "%{$term}%"); }) ->orWhereHas('maintenance', function ($query) use ($term) { $query->where('description', 'LIKE', "%{$term}%"); }) ->get();
用查询日志排查具体SQL
要是还找不到问题,建议打开Laravel的查询日志,看看实际生成的SQL语句,一眼就能看出哪个条件没被正确添加:
// 开启查询日志 DB::enableQueryLog(); // 执行你的关联查询代码 $vehicles = Vehicle::query()...->get(); // 打印生成的SQL,排查问题 dd(DB::getQueryLog());
通过查看SQL,你能清楚看到两个关联查询的条件是否都被正确拼接,有没有语法错误或者变量缺失的情况。
额外提醒:别搞混with和whereHas
如果你是用with预加载关联数据并加过滤条件,那with的闭包只会过滤预加载的关联数据,不会过滤主模型;而whereHas是过滤主模型(只返回满足关联条件的主模型),搞混两者也会让你误以为其中一个关联查询没生效。
内容的提问来源于stack exchange,提问作者samaritanfruit
相关产品推荐
相关产品推荐

