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

Laravel合并多模型Eloquent集合并按created_at排序的问题

合并多个Eloquent集合并排序的实用方案

嘿,我来帮你梳理下在Laravel里合并多个不同模型的Eloquent集合,还能按你想要的规则排序的正确姿势~

首先你原来的代码其实可以简化,没必要手动实例化ModelCollection,毕竟每个Eloquent查询返回的都是Laravel自带的Illuminate\Database\Eloquent\Collection,直接用集合本身的方法就足够了。另外要提个醒:你用到了created_at来排序,得确保Product、Slider还有你的News模型(哪怕数据还没补全)对应的数据库表都有这个字段,不然排序的时候可能会出问题哦。

优化后的代码

// 先分别获取各个模型的数据集
$products = Product::orderBy('created_at', 'desc')->get();
$sliders = Slider::orderBy('order', 'asc')->get();
$news = News::orderBy('order', 'asc')->get();

// 直接合并三个集合并按created_at倒序排序
$result = $products->merge($news)->merge($sliders)->sortByDesc('created_at');

// 如果你喜欢从空集合开始合并也可以,效果完全一样
// $result = collect()->merge($products)->merge($news)->merge($sliders)->sortByDesc('created_at');

dd($result);

几个要注意的点

  • 合并顺序的影响:merge是把后面集合的元素追加到前面的集合里,要是不同模型有重复的主键(不过你这三个是不同模型,基本不会碰到),后面的元素会覆盖前面的,这点你不用太担心。
  • 排序字段的完整性:一定要确认三个模型都有created_at字段,而且数据里这个字段是有有效值的。要是你的News里有些数据没有created_at,可以给这些数据设置一个默认的早日期,让它们排序时自动排到最后,代码可以这么改:
$result = $products->merge($news)->merge($sliders)->sortByDesc(function ($item) {
    // 没有created_at的话就用1970年的日期,保证排最后
    return $item->created_at ?? Carbon::parse('1970-01-01');
});
  • 集合类型不用纠结:Eloquent查出来的集合已经自带了所有你需要的方法,完全不用额外去实例化ModelCollection,省点代码更清爽~

内容的提问来源于stack exchange,提问作者Ali Özen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:24:13