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 协议》,转载必须注明作者和本文链接
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 12

在模型里写 take (3)

6年前 评论

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

6年前 评论

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

6年前 评论
wenber

hasMany 后 take 不行吗?

6年前 评论

我前段时间也咨询过这个问题
问答:请问如何查询每个分类下的前 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();
6年前 评论

首先你没有搞清楚预加载的原理,预加载首先会一次性查询出符合外键查询需求的所有数据,然后脱离 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();
6年前 评论

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

6年前 评论

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

6年前 评论

@zh117 唯有 redis 拯救大局了。

6年前 评论
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 试试.

6年前 评论