Laravel 按分页排序
Posted
技术标签:
【中文标题】Laravel 按分页排序【英文标题】:Laravel sortBy paginate 【发布时间】: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 是一个未定义的方法。
【问题讨论】:
【参考方案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();
使用 skip
和 take
但我不是 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从功能上来说会代替。以上是关于Laravel 按分页排序的主要内容,如果未能解决你的问题,请参考以下文章