ORM 下如何实现同类别下同数量内容输出?

$list = Category::whereIn('id', [3, 4, 5, 6])->with(['posts' => function($q) { $q->take(3); }])
Category 模型中 return $this->hasMany('App\Models\Post')

这样无效,请问还有其他办法吗?我想一次输出每个类别下的3条数据。

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 12

在模型里写take(3)

5年前 评论

@木子龙 不行啊,我要每个输出3条,模型里写只有第一个输出3条,(所有总共只有3条)

5年前 评论

这个实现不了吧,乖乖的循环去取吧

5年前 评论
wenber

hasMany后take不行吗?

5年前 评论

我前段时间也咨询过这个问题
问答:请问如何查询每个分类下的前 N 条记录?
后来我是这样解决的

ArticleCategory::whereIn('id', [1, 2, 3])->with(['articles' => function ($query) {
    $table = $query->getRelated()->getTable(); //获取当前依赖表名称
    $query->whereRaw('( SELECT COUNT(*) FROM `' . $table . '` AS `temp` WHERE `' . $table . '`.`category_id` = `temp`.`category_id` AND `' . $table . '`.`id` > `temp`.`id`) <= 10'); //10获取10条记录 (table.id > temp.id) >号ID从小到大,<号获取最新的
}])->get();
5年前 评论

首先你没有搞清楚预加载的原理,预加载首先会一次性查询出符合外键查询需求的所有数据,然后脱离mysql后进行配对的。你限制了总共查询3条数据等于总共查询出了3条,所以只能配对这3条数据。
所以你的思路应该变更为如何让第一次一次性查询到的数据刚好服你的每条只要前3条的需求,筛选出这些ID,然后再用回调的query去获取对应的值就好;
这里关系表只是举例,你更换表名即可;

$list = Category::query()->whereIn('id', [1,2])
         ->with(['topics' => function($q) {

                $topics = Topic::query()->whereIn('category_id',[1,2])
                    ->select('id','category_id')
                    ->get()
                    ->groupBy('category_id');

                $col = collect();

                foreach ($topics as $topic) {
                    $res = $topic->filter(function ($value, $key) {
                        return $key < 3;
                    });
                    $col = $col->merge($res);
                }

                $ids = $col->pluck('id')->toArray();

                $q->find($ids);
            }])
            ->get();
5年前 评论

@zh117 全部查出来再过滤会不会不太好,假如第一次查出来数量巨大呢?

5年前 评论

@waney 这就要看你业务的具体需求了,这个方法也仅仅是迎合题意。如果你是真实业务需求,redis弄个list或set都可以,速度绝对流畅。如果一定要用mysql的话,把第一步whereIn换成循环limit 3吧。如果分类少的话还是很流畅的。

5年前 评论
jltxwesley

@waney

public function threePosts()
{
    return $this->hasMany('App\Models\Post')->take(3);
}

$categories = Category::whereIn('id', [3, 4, 5, 6])->get();
$categories->each(function ($category) {
    $category->load('threePosts');
});

然后你再循环输出categorythreePost试试.

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!