Laravel中如何使用多个过滤器对合并的多表集合数据进行筛选
问题根因
筛选不生效是三个问题共同导致的:
- Laravel 集合的绝大多数操作方法都是返回新的集合实例,不会修改原集合本身。你的代码里调用了
$results->when()之后没有把返回的新集合赋值给$results变量,原变量始终保存的是未过滤的合并数据集。 when方法的回调函数需要返回处理后的集合实例,你原代码的回调中没有写return语句,过滤逻辑执行后没有把结果传递出去。- 集合的
where方法官方定义为小写写法,你写的大写Where虽然PHP语法不区分方法名大小写,但不符合规范,也建议修正。
额外说明:你当前的实现是先把两张表的全量数据都查出来加载到内存中,再做合并和筛选,数据量较大时会占用极高内存、执行效率极低,更推荐在SQL层面完成合并和筛选操作。
解决方案1:修复现有集合操作逻辑
如果确认要在内存中处理数据,修改代码如下即可生效:
$data1 = collect(DB::table('table_1')->get()->toArray()); $data2 = collect(DB::table('table_2')->get()->toArray()); $results = $data1->merge($data2); if ($request->name != "") { // 接收when方法返回的新集合,回调中返回过滤后的集合 $results = $results->when(request('name'), function($q){ return $q->where('name', request('name')); }); } // 其他筛选逻辑都遵循「接收返回值+回调return」的规则 ... return $results;
解决方案2:SQL层面union实现(更推荐)
直接在数据库层完成表合并和筛选,避免全量数据查询,性能提升明显:
// 构造两个表的union查询,两个表的select字段顺序、类型必须完全对应 $union = DB::table('table_1') ->select('id', 'name', '其他需要返回的字段') ->union( DB::table('table_2')->select('id', 'name', '其他需要返回的字段') ); // 对合并后的结果集加筛选条件 $results = DB::table(DB::raw("({$union->toSql()}) as merged_tables")) ->mergeBindings($union) ->when($request->filled('name'), function($query) use ($request) { return $query->where('name', $request->input('name')); }) // 其他筛选条件可继续在后面拼接 // ... ->get(); return $results;
内容的提问来源于stack exchange,提问作者راجہ سفیان
相关产品推荐
相关产品推荐

