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

Laravel中如何合并多个模型并实现分页展示?

多模型合并分页的正确实现方法

你的代码无法运行的核心问题:merge([$story,$video])是将两个集合作为数组元素嵌套合并到$post集合中,导致最终集合里包含子集合而非平级的模型实例,因此无法正常执行分页逻辑。

下面提供两种可行的解决方案:

方案1:集合链式合并(适合小数据量)

保持集合合并的思路,通过链式调用merge方法逐个合并单个集合,确保所有模型实例处于同一层级:

public function show($tags)
{
    $tagLike = "%{$tags}%";
    
    $post = Post::where('keywords', 'LIKE', $tagLike)->get();
    $story = Story::where('keywords', 'LIKE', $tagLike)->get();
    $video = Video::where('keywords', 'LIKE', $tagLike)->get();
    $game = Game::where('keywords', 'LIKE', $tagLike)->get();

    // 链式合并所有集合,避免嵌套
    $merged = $post->merge($story)->merge($video)->merge($game);
    $results = $merged->paginate(12);

    return view('tags', compact('results'));
}

方案2:数据库层面联合查询(推荐,性能更优)

方案1属于内存分页,会先拉取所有符合条件的数据到服务器内存再分页,数据量大时性能极差。推荐通过数据库的unionAll实现联合查询后分页,这是真正的数据库级分页:

use Illuminate\Support\Facades\DB;

public function show($tags)
{
    $tagLike = "%{$tags}%";

    // 构建各模型的查询构造器(不要调用get()),确保字段数量/类型一致
    $postQuery = Post::select(
        'id', 
        'title', 
        'keywords', 
        'created_at', 
        DB::raw("'post' as model_type") // 标记数据所属模型,方便前端区分
    )->where('keywords', 'LIKE', $tagLike);

    $storyQuery = Story::select(
        'id', 
        'title', 
        'keywords', 
        'created_at', 
        DB::raw("'story' as model_type")
    )->where('keywords', 'LIKE', $tagLike);

    $videoQuery = Video::select(
        'id', 
        'title', 
        'keywords', 
        'created_at', 
        DB::raw("'video' as model_type")
    )->where('keywords', 'LIKE', $tagLike);

    $gameQuery = Game::select(
        'id', 
        'title', 
        'keywords', 
        'created_at', 
        DB::raw("'game' as model_type")
    )->where('keywords', 'LIKE', $tagLike);

    // 合并查询并分页
    $results = $postQuery
        ->unionAll($storyQuery)
        ->unionAll($videoQuery)
        ->unionAll($gameQuery)
        ->orderBy('created_at', 'desc') // 可选:按创建时间倒序排列
        ->paginate(12);

    return view('tags', compact('results'));
}

关键注意点:

  • 使用unionAll时,每个子查询的字段数量、顺序和数据类型必须完全匹配,否则会报错。
  • 添加model_type字段可以在前端轻松区分不同模型的数据,方便渲染不同的样式或逻辑。
  • 避免SQL注入:虽然Laravel会自动转义LIKE语句中的变量,但如果需要更严谨的写法,可以使用whereRaw('keywords LIKE ?', [$tagLike])。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 15:25:22