You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel筛选值非空时动态添加where/whereIn条件的最优方案

Laravel多筛选项动态查询最优实现

不用多层if-else拆查询拼接,直接用Laravel查询构造器原生提供的when()方法即可,逻辑内聚在查询链上,可读性高,没有额外性能开销。

第一步:提前预处理所有请求参数

不要把参数格式化逻辑混在查询链里,统一先处理完所有入参默认值、格式转换:

$perPage = 20;
// 批量提取需要的筛选项,不用逐个调用$request取参
$filters = $request->only([
    'input1', 'input2', 'start_date', 'end_date', 'process', 'status', 'user_id'
]);

// 格式化日期参数
if (!empty($filters['start_date'])) {
    $filters['start_date'] .= ' 00:00:00';
}
if (!empty($filters['end_date'])) {
    // 注意:原逻辑拼00:00:00会漏掉结束日期当天的所有数据,这里修正为23:59:59
    $filters['end_date'] .= ' 23:59:59';
}
// 流程参数默认值
if (empty($filters['process'])) {
    $filters['process'] = [1,2,3,4];
}

第二步:链式调用when追加动态条件

when()方法接收三个参数:第一个是判断条件,条件为真时执行第二个闭包追加查询,条件为假时执行第三个可选闭包,完全匹配“非空才加条件、不同值走不同查询逻辑”的需求:

$items = DB::table('transactions_tbl')
    ->select([/* 你需要查询的字段数组 */])
    ->leftJoin('tbl_1 as table1', 'table1.id', '=', 'transactions_tbl.tbl1_f_key')
    ->leftJoin('tbl_2 as table2', 'table2.id', '=', 'transactions_tbl.tbl2_f_key')
    // input1非空时追加等值查询
    ->when(!empty($filters['input1']), function ($query) use ($filters) {
        $query->where('transactions_tbl.input1', $filters['input1']);
    })
    // input2非空时追加等值查询
    ->when(!empty($filters['input2']), function ($query) use ($filters) {
        $query->where('transactions_tbl.input2', $filters['input2']);
    })
    // process逻辑:传了有效值走where单值匹配,没传走默认数组的whereIn
    ->when(!empty($request->input('process')), function ($query) use ($filters) {
        $query->where('transactions_tbl.process', $filters['process']);
    }, function ($query) use ($filters) {
        $query->whereIn('transactions_tbl.process', $filters['process']);
    })
    // 开始时间条件
    ->when(!empty($filters['start_date']), function ($query) use ($filters) {
        $query->where('transactions_tbl.created_at', '>=', $filters['start_date']);
    })
    // 结束时间条件
    ->when(!empty($filters['end_date']), function ($query) use ($filters) {
        $query->where('transactions_tbl.created_at', '<=', $filters['end_date']);
    })
    // 状态条件
    ->when(!empty($filters['status']), function ($query) use ($filters) {
        $query->where('transactions_tbl.status', $filters['status']);
    })
    // 指派用户条件
    ->when(!empty($filters['user_id']), function ($query) use ($filters) {
        $query->where('transactions_tbl.assigned_user', $filters['user_id']);
    })
    ->paginate($perPage);

筛选项更多时的简化写法

如果后续筛选项增加到10个以上,可以把通用的等值查询抽成映射数组批量处理,减少重复代码:

// 配置等值查询的字段和参数映射:[数据库字段名 => 对应请求参数键名]
$equalFilterMap = [
    'transactions_tbl.input1' => 'input1',
    'transactions_tbl.input2' => 'input2',
    'transactions_tbl.status' => 'status',
    'transactions_tbl.assigned_user' => 'user_id'
];

// 初始化基础查询
$query = DB::table('transactions_tbl')
    ->select([/* 查询字段数组 */])
    ->leftJoin('tbl_1 as table1', 'table1.id', '=', 'transactions_tbl.tbl1_f_key')
    ->leftJoin('tbl_2 as table2', 'table2.id', '=', 'transactions_tbl.tbl2_f_key');

// 批量追加通用等值条件
foreach ($equalFilterMap as $column => $paramKey) {
    $query->when(!empty($filters[$paramKey]), function ($q) use ($column, $filters, $paramKey) {
        $q->where($column, $filters[$paramKey]);
    });
}

// 单独追加特殊逻辑的条件(非等值、区间、默认值类条件)
$query->when(!empty($request->input('process')), function ($q) use ($filters) {
    $q->where('transactions_tbl.process', $filters['process']);
}, function ($q) use ($filters) {
    $q->whereIn('transactions_tbl.process', $filters['process']);
})
->when(!empty($filters['start_date']), function ($q) use ($filters) {
    $q->where('transactions_tbl.created_at', '>=', $filters['start_date']);
})
->when(!empty($filters['end_date']), function ($q) use ($filters) {
    $q->where('transactions_tbl.created_at', '<=', $filters['end_date']);
});

// 最终分页取数
$items = $query->paginate($perPage);

注意事项

  • 判断参数非空不要用isset(),如果参数有效值是0或字符串"0"会被误判为空,根据业务场景选择!empty()或者更严谨的判断规则
  • 日期条件如果不想手动拼接字符串,可以直接用whereDate/whereBetween方法,省去时间字符串拼接的出错可能
  • 该写法和多层if拼接的SQL生成逻辑完全一致,没有额外性能损耗,不会追加无效的where条件

内容的提问来源于stack exchange,提问作者newCode

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 07:54:23