Laravel 5.4如何同时检索article与news表并统一排序
解决跨article和news表的联合搜索需求
嘿,刚好我之前处理过类似的场景,给你两种靠谱的实现方案,按需选择就行:
方案一:数据库层面Union合并(推荐,性能更优)
这种方法直接在数据库里把两个表的查询结果合并,然后统一排序分页,适合数据量较大的场景,能减少内存消耗。
核心思路是给每个查询结果手动添加type字段区分来源表,再用union合并两个查询,最后统一按created_at倒序排序:
$query = $request['search']; // 构造article表的查询,手动加入type标识 $articleQuery = DB::table('article') ->select('id', 'title', 'created_at', DB::raw("'article' as type")) ->where('title', 'LIKE', "%{$query}%"); // 注意用双引号或字符串拼接,确保变量被解析 // 构造news表的查询,添加type后合并article的查询 $searchResult = DB::table('news') ->select('id', 'title', 'created_at', DB::raw("'news' as type")) ->where('title', 'LIKE', "%{$query}%") ->union($articleQuery) ->orderBy('created_at', 'desc') ->paginate(10);
关键注意点:
- 两个
select语句返回的字段数量、类型必须一致,否则union会报错; - 你的原代码里用了单引号
'%$query%',这会导致变量$query无法被解析,一定要改成"%{$query}%"或者'%' . $query . '%'。
方案二:集合合并(适合表结构差异大的场景)
如果两张表的字段差异较大,没法用union的话,可以先分别查询两张表,把结果转换成集合后添加type标识,再合并排序分页:
use Illuminate\Pagination\LengthAwarePaginator; $query = $request['search']; // 查询article并添加type标识 $articles = DB::table('article') ->where('title', 'LIKE', "%{$query}%") ->get() ->map(function ($item) { $item->type = 'article'; return $item; }); // 查询news并添加type标识 $news = DB::table('news') ->where('title', 'LIKE', "%{$query}%") ->get() ->map(function ($item) { $item->type = 'news'; return $item; }); // 合并集合并按created_at倒序排序 $mergedResults = $articles->merge($news)->sortByDesc('created_at'); // 手动创建分页器(集合本身没有paginate方法) $page = request()->get('page', 1); $perPage = 10; $searchResult = new LengthAwarePaginator( $mergedResults->forPage($page, $perPage), $mergedResults->count(), $perPage, $page, ['path' => request()->url(), 'query' => request()->query()] // 保证分页链接正确 );
关键注意点:
- 这个方法会把两张表的匹配结果全部加载到内存,数据量很大时性能会受影响,更适合小数据量场景;
- 记得引入
LengthAwarePaginator类,否则会触发类不存在的错误。
两种方法都能实现你要的「同时检索两张表、标注结果类型、统一按created_at倒序排序」的需求,根据你的实际场景选就行~
内容的提问来源于stack exchange,提问作者Agil
相关产品推荐
相关产品推荐

