【问题标题】:Laravel sortBy paginateLaravel 按分页排序
【发布时间】:2014-12-10 13:27:50
【问题描述】:

我有一个 posts 表和 cmets 表,comment 属于 post,并且我在 Post 和 Comment 模型中有关系设置。我确实按照每个帖子的 cmets 数量对帖子进行了排序,如下所示:

      $posts = Post::with('comments')->get()->sortBy(function($post) {
           return $post->comments->count();
      });

我想知道如何对这些排序的帖子进行分页?

      $posts = Post::with('comments')->get()->sortBy(function($post) {
           return $post->comments->count();
      })->paginate(20);

不起作用并给我一个错误,说 paginate 是一个未定义的方法。

【问题讨论】:

    标签: laravel laravel-4 eloquent pagination laravel-paginate


    【解决方案1】:

    我不知道你是否可以使用 Eloquent 来做到这一点,但你可以使用 join 来做到这一点:

    $posts = Post::leftJoin('comments','posts.id','=','comments.post_id')->
                   selectRaw('posts.*, count(comments.post_id) AS `count`')->
                   groupBy('posts.id')->
                   orderBy('count','DESC')->
                   paginate(20);
    

    但是,在这种情况下,似乎所有记录都是从数据库中获取的,并且只显示来自分页器的记录,所以如果您有很多记录,那就是资源浪费。看来您应该为此进行手动分页:

    $posts = Post::leftJoin('comments','posts.id','=','comments.post_id')->
                   selectRaw('posts.*, count(comments.post_id) AS `count`')->
                   groupBy('posts.id')->
                   orderBy('count','DESC')->
                   skip(0)->take(20)->get();
    

    使用 skiptake 但我不是 Eloquent 专家,也许有更好的解决方案可以实现您的目标,所以您可以等待,也许有人会给出更好的答案。

    【讨论】:

    • 谢谢,所以要明确一点,这个解决方案不会从数据库中获取所有记录然后对其进行排序,它一开始只获取20条记录对吗?
    • @dulan,是的,如果我们谈论的是第二个代码。在第一个代码中,所有记录都将从数据库中获取并仅显示其中一些记录,因此您需要选择第二个解决方案
    【解决方案2】:

    这听起来很明显,但 Eloquent 不会在这里返回结果集,而是会返回一个集合。

    如果你深入研究源码(Builder::get调用Builder::getFresh,调用Builder::runSelect,调用Connection::select),你会发现它的意图是简单地返回结果,然后将结果放入一个集合(具有 sortBy 方法)。

    /**
     * Run a select statement against the database.
     *
     * @param  string  $query
     * @param  array  $bindings
     * @param  bool  $useReadPdo
     * @return array
     */
    public function select($query, $bindings = array(), $useReadPdo = true)
    {
      return $this->run($query, $bindings, function($me, $query, $bindings) use ($useReadPdo)
      {    
        if ($me->pretending()) return array();
    
        // For select statements, we'll simply execute the query and return an array
        // of the database result set. Each element in the array will be a single
        // row from the database table, and will either be an array or objects.
        $statement = $this->getPdoForSelect($useReadPdo)->prepare($query);
    
        $statement->execute($me->prepareBindings($bindings));
    
        //** this is a very basic form of fetching, it is limited to the PDO consts.
        return $statement->fetchAll($me->getFetchMode());
      });  
    }
    

    如果你想在不加载每个项目的情况下进行分页,那么你需要使用@Marcin的解决方案(复制如下):

    $posts = Post::leftJoin('comments','posts.id','=','comments.post_id')->
               selectRaw('posts.*, count(comments.post_id) AS `count`')->
               groupBy('posts.id')->
               orderBy('count','DESC')->
               skip(0)->take(20)->get();
    

    【讨论】:

      【解决方案3】:

      只需删除链式调用中的get(),看看你得到了什么,paginate 应该替换 get() 调用。

      【讨论】:

      • 这行不通。 sortBy 用于结果集,因此使用 paginate 使得仅对前 20 行而不是所有记录进行排序。这就是区别。先排序再分页不相反
      • 我建议他把get()去掉,不要用paginate()代替,paginate从功能上来说会代替。
      猜你喜欢
      • 1970-01-01
      • 2018-03-18
      • 2021-07-14
      • 2019-11-24
      • 2022-01-22
      • 1970-01-01
      • 2023-03-10
      • 2014-02-24
      • 2019-09-16
      相关资源
      最近更新 更多