使用 Eloquent 对数据进行排序

12

我刚接触Laravel(从CI转过来),但Eloquent ORM在某些方面仍然有些神秘!

这是我的问题:

我想使用Eloquent从数据库中排序数据。

我有一个名为posts的表和一个名为comments的表(每个post都有很多评论,每个评论属于文章)

每个评论都有一个时间戳(=> created_at字段),我想按照以下方式排序:

(我们在个人资料页面,因此$user->id是用户的ID(显然))

我希望得到该用户发表评论的所有文章,并将这些文章根据评论的created_at字段排序

我真的想充分利用Eloquent或至少使用Fluent,但我不知道正确的方法。

我希望我表述清楚了,谢谢你的时间!

5个回答

20

我在开发一个项目时遇到了同样的问题。无论我看到哪里,都建议使用usort()uasort()来解决这个问题。(Collection::sort()只是uasort()的一个包装器)但这并不能令我满意,因为我为什么要使用PHP进行排序,SQL应该在ORDER BY子句中帮我完成它??? 最终,我采用了getXXXAttribute()方法实现了它:

class Post extends Eloquent {
    public function comments()
    {
        return $this->hasMany('Comment');
    }

    public function getCommentsAttribute()
    {
        $comments = $this->comments()->getQuery()->orderBy('created_at', 'desc')->get();
        return $comments;
    }
    ...
}

这个是对评论还是帖子进行排序? - Glad To Help
4
这个解决方案似乎已经过时。不知道它们实际上是何时实现的,但是您可以通过查询函数扩展关系。因此,在这种情况下,您只需编写return $this->hasMany('Comment')->orderBy('created_at', 'desc')来源 - mwallisch
Collection::sort()的链接已损坏。 - Spudley

3

我之前也遇到过类似的问题,但只是一个一对一的关系。这个帖子对我有所帮助。最终我使用了join操作,我的代码如下:

$data = Posts::join('comments', 'comments.post_id', '=', 'posts.id')
        ->order_by('comments.created_at')
        ->get(array('comments.field1 as field1', 'posts.field2 as field2'));

3

谢谢您的时间,但那并不起作用:这是因为查询没有过滤帖子而是评论。结果是,我得到了所有的帖子,而且它们没有排序。为什么在Laravel中这样一个简单的操作会如此困难?我尝试使用Fluent,但我必须承认我讨厌它...您有其他想法吗? - Pretty Good Pancake

1
如果您的用户类中定义了关系,则可以通过评论获取所有帖子。它返回一个集合,其中提供了sortBy()和sortByDesc()函数。这两个函数都将接受一个回调函数,在其中可以选择自己的排序方法。
$posts = $user->comments->post->sortByDesc(function($post) {
    return $post->created_at;
});

0
你面临的问题是因为你定义的关系只是给你与帖子相关联的评论和一个“Order By”结果,这只会对评论进行排序,因为评论是输出的内容,所以你可以在评论模型中定义“Comments”属于“Post”,然后找到评论关联的帖子并使用usort()函数运行手动比较,例如(我正在用Laravel 3编写代码,但你可以为任何其他版本重新编写它):
假设你的评论表有一个名为postID的外键,它定义了与帖子表的关系,帖子表中的时间戳是默认的created_at,用户表与评论表连接,并具有外键userid
    $userid = $user->id;
    $comments = Comments::where_userid($userid);
    function commentsort($first, $second){
      if (getCommentPost($first) == getCommentPost($second)) {
        return 0;
      }
     return (getCommentPost($first) < getCommentPost($second)) ? -1 : 1;
    }

    function getCommentPost($comment){
    return Post::where_postid($comment->postid)->first()->created_at;
    }

    usort($comments, "commentsort");

这应该有助于解决问题。实际上,Laravel 没有包含此功能,因为它是一个框架,而执行特定功能的函数通常不包括在框架中,因为使用范围有限。话虽如此,您也可以将此函数包含在默认的 DB 类中,以便在项目中普遍使用此功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接