5

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

      $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 是一个未定义的方法。

4

3 回答 3

6

我不知道你是否可以使用 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();

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

于 2014-10-15T13:37:13.297 回答
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();
于 2014-10-15T20:10:31.793 回答
-1

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

于 2014-10-15T17:46:29.750 回答