【问题标题】:Laravel 4.1: How to paginate eloquent eager relationship?Laravel 4.1:如何分页雄辩的渴望关系?
【发布时间】:2014-01-03 22:10:00
【问题描述】:

有关于旧的 L3 急切加载分页的问题,而不是使用 eloquent。但我想使用 eloquent 来获得与分页的渴望加载关系。

主模型:TopicPosts有一对多关系, 这样一个Topic就有很多Posts。我用这个函数获取所有数据:

public function findById($id)
{
    return $this->topic->with('posts', 'posts.user', 'posts.user.profile')
                       ->find($id);
}

后来我循环显示所有结果,但它们没有分页:

@foreach($topic->posts as $post)
... unpaginated content ...
@endforeach

所以,我可以制定一个解决方法,分别选择所有具有 $id of topic 的帖子并使用 ->paginate() 而不是 ->get() 并且会分页 $pots,

  1. 但是是否有可能使用分页的急切加载关系posts?又是如何做到的?

【问题讨论】:

    标签: php laravel pagination eloquent


    【解决方案1】:

    澄清一下:对急切加载的关系进行分页有点误解。急切加载的目的是在尽可能少的查询中检索所有关系。如果要检索 10 个主题,所有主题都有 35 个帖子,则只需要两次查询。甜!

    也就是说,为急切加载的关系分页是行不通的。考虑急切加载发生时的两种情况:

    1. 您想要检索和列出主题,并可能列出每个主题的前五个帖子。伟大的!急切加载是完美的。现在,您不会想在这样的页面上对预先加载的帖子进行分页,所以没关系。

    2. 您加载了一个主题,并且想要为该主题的帖子分页。伟大的!做起来比较容易。但是,如果您已经预先加载了属于该主题的所有个帖子,那么您可能会检索到很多您不需要的额外资源。因此,急切加载实际上是伤害你。

    也就是说,有两种可能的解决方案:

    选项 1:创建一个对 Eloquent 关系进行分页的自定义访问器。

    /**
     * Paginated posts accessor. Access via $topic->posts_paginated
     * 
     * @return \Illuminate\Pagination\Paginator
     */
    public function getPostsPaginatedAttribute()
    {
        return $this->posts()->paginate(10);
    }
    

    优点:很容易分页;不干扰正常发帖关系。
    缺点:急于加载帖子不会影响此访问器;运行它将在急切加载的查询之上创建两个额外的查询。

    选项 2:对预先加载的关系返回的帖子集合进行分页。

    /**
     * Paginated posts accessor. Access via $topic->posts_paginated
     * 
     * @return \Illuminate\Pagination\Paginator
     */
    public function getPostsPaginatedAttribute()
    {
        $posts = $this->posts;
    
        // Note that you will need to slice the correct array elements yourself.
        // The paginator class will not do that for you.
    
        return \Paginator::make($posts, $posts->count(), 10);
    }
    

    优点:使用预先加载的关系;不会创建额外的查询。
    缺点:无论当前页面如何,都必须检索所有元素(慢);必须手动构建当前页面元素。

    【讨论】:

    • 感谢您的精彩解释,选项 1 现在对我来说是正确的选择。我问的是急切加载,因为我认为这是通过 $topic 访问帖子的唯一方法,但选项 1 做得很好,也可以进行分页,这正是我想要的。 $topic->posts_paginated->links() 可以用来生成链接吗?
    • 是的,它会返回一个 Paginator 对象,就像 Eloquent 查询结束时的普通 ->paginate(10) 一样。
    • 问题是,如果我在数据库中有 1000 个 cmets,并且即使属性分页正确,性能也会下降。那么有什么方法可以直接在 Eloquent 查询中为每个 Topic 限制 10 个帖子?
    • 如果我想加载主题,并列出该主题的所有帖子,但一次只显示 10 个主题。听起来我想要 Topic::with('posts')->paginate(10),这是一个你似乎错过的用例。
    • @Benubird 这正是您想要的,但它与为急切加载的关系分页不同。使用您的示例,本主题侧重于对posts 关系进行分页,而不是原始主题。
    【解决方案2】:

    您可能想看看以下内容:

    $category = 'Laravel';
    
    $posts = Post::with('user', 'category')->whereHas('category', function($query) use ($category) {
    $query->where('name', '=', $category);
    })->paginate();
    

    Zenry : 来源:http://laravel.io/forum/02-25-2014-eager-loading-with-constrains-load-post-based-on-category-name

    希望对你有帮助

    【讨论】:

    • 当然,这对我来说效果更好。与其尝试对急切加载的关系进行分页,不如倒过来考虑。这样你就可以简单地抓取所有“whereHas”主题的帖子,然后对其进行分页。
    猜你喜欢
    • 2020-05-10
    • 1970-01-01
    • 2015-09-18
    • 2015-03-14
    • 2018-11-28
    • 2015-01-11
    • 2021-06-03
    • 2020-03-26
    相关资源
    最近更新 更多