
在 laravel 中,直接链式调用 `where()` 和 `orwhere()` 会导致 sql 优先级错误,使原有条件(如 `airline_id`)失效;必须通过闭包逻辑分组将 or 条件括起来,确保 and 与 or 的布尔逻辑符合业务预期。
当你在 Laravel Eloquent 中编写如下查询时:
Product::with('airline')
->where('airline_id', $request->airline_id)
->select('id','name','code')
->where("name","LIKE","%{$request->search}%")
->orWhere("code","LIKE","%{$request->search}%")
->limit(5)
->get();实际生成的 SQL 是:
WHERE airline_id = ? AND name LIKE ? OR code LIKE ?
由于 OR 的优先级低于 AND,整个条件等价于:
WHERE (airline_id = ? AND name LIKE ?) OR (code LIKE ?)
这意味着:只要 code 匹配任意值,即使 airline_id 不匹配,该记录也会被返回——这正是你看到“其他航司产品混入”的根本原因。
✅ 正确做法是使用 逻辑分组(Query Scopes with Closure),将 name 或 code 的搜索条件包裹在一个括号内,使其整体作为 airline_id 条件的子条件:
Product::with('airline')
->select('id', 'name', 'code')
->where('airline_id', $request->airline_id)
->where(function ($query) use ($request) {
$query->where('name', 'LIKE', "%{$request->search}%")
->orWhere('code', 'LIKE', "%{$request->search}%");
})
->limit(5)
->get();生成的 SQL 将变为:
WHERE airline_id = ? AND (name LIKE ? OR code LIKE ?)
✅ 完全符合语义预期:仅返回指定航司下、名称或编码匹配搜索关键词的产品。
⚠️ 注意事项:
- 所有需统一逻辑层级的 OR 条件,都应置于 where() 闭包中;
- 若搜索字段可能为空(如 $request->search 未填写),建议提前校验并跳过搜索条件,避免生成 WHERE ... AND (name LIKE '%%' OR code LIKE '%%') 这类低效甚至全表扫描查询;
- 可进一步封装为本地作用域(Local Scope),提升复用性:
// In Product model
public function scopeSearchByNameOrCode($query, $term)
{
if (trim($term)) {
return $query->where(function ($q) use ($term) {
$q->where('name', 'LIKE', "%{$term}%")
->orWhere('code', 'LIKE', "%{$term}%");
});
}
return $query;
}
// Usage:
Product::where('airline_id', $request->airline_id)
->searchByNameOrCode($request->search)
->select('id','name','code')
->limit(5)
->get();掌握逻辑分组不仅是修复 orWhere 副作用的关键,更是构建健壮、可维护查询的基础能力。










