贝利信息

Laravel 查询中正确使用 WHERE 和 ORWHERE 的逻辑分组方法

日期:2026-01-24 00:00 / 作者:花韻仙語

在 laravel 中,当混合使用 where() 和 orwhere() 时,若不进行逻辑分组,会导致 sql 运算符优先级错误,使原本应受约束的条件(如 airline_id)失效。解决方法是用闭包包裹 or 条件,确保其整体与主条件构成 and 关系。

你遇到的问题源于 SQL 的运算符结合顺序:原始代码

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 实际等价于:

SELECT `id`, `name`, `code` 
FROM `products` 
WHERE `airline_id` = ? AND `name` LIKE ? OR `code` LIKE ?

由于 AND 优先级高于 OR,该语句被解析为:
(airline_id = ? AND name LIKE ?) OR code LIKE ?
→ 导致 code 匹配时完全忽略

airline_id 限制,从而泄露其他航空公司的产品。

✅ 正确做法是使用 逻辑分组(Logical Grouping),将 name 或 code 的搜索条件封装在闭包中,使其整体作为单个子条件参与外层 AND 运算:

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 将变为:

SELECT `id`, `name`, `code` 
FROM `products` 
WHERE `airline_id` = ? AND (`name` LIKE ? OR `code` LIKE ?)

✅ 语义清晰、逻辑严谨,严格限定结果仅属于指定航空公司,同时支持按名称或编码模糊搜索。

⚠️ 注意事项:

->when($request->filled('search'), function ($query) use ($request) {
    $query->where(function ($q) use ($request) {
        $q->where('name', 'LIKE', "%{$request->search}%")
          ->orWhere('code', 'LIKE', "%{$request->search}%");
    });
})

这样既保持代码可读性,又提升健壮性与可维护性。