雄辩的一对多秩序

时间:2014-03-06 19:15:21

标签: laravel laravel-4 eloquent

我正在与一对多关系中的Eloquent合作。

我想通过使用他们的上一篇文章DateTime(created_at)来订购我的用户,但我无法弄清楚如何使这项工作。

表用户:

 id | name 
 1  | John 
 2  | Doe
 3  | Foo
 4  | ...

表格帖子:

id | title  | body  | user_id | created_at 
1  | Title 1| Body1 | 1       | 2014-03-06 14:00:00
2  | Title 2| Body2 | 1       | 2014-03-04 14:00:00
3  | Title 3| Body3 | 2       | 2014-03-03 14:00:00
4  | Title 4| Body4 | 3       | 2014-03-05 14:00:00

期望的最终输出示例:

name | title   | created_at
John | Title 1 | 2014-03-06 14:00:00
Foo  | Title 4 | 2014-03-05 14:00:00
Doe  | Title 3 | 2014-03-03 14:00:00

我能越接近:

$users = User::with(['posts' => function($query){
     $query->orderBy('created_at', 'desc');
}])->get();

但是这段代码会提取每个用户的所有帖子,而我只想要最后一个帖子。

你能帮帮我吗?感谢。

更新:我终于找到了我要找的内容:检索用户的上一篇文章,并按升序排序(最后一篇帖子的时间戳)。随意改进此查询!

$users = DB::table('posts')
    ->join('users', 'posts.user_id', '=', 'users.id')
    ->select(DB::raw('posts.id, posts.user_id, MAX(created_at) as created_at'))
    ->groupBy('posts.user_id')
    ->orderBy('created_at', 'asc')
    ->get();

2 个答案:

答案 0 :(得分:0)

你可以试试这个:

$users = User::with(array('posts' => function($query){
    $query->orderBy('created_at', 'desc')->groupBy('user_id');
}))->get();

更新:您可以尝试这样做:

$users = User::join('posts', 'users.id', '=', 'posts.user_id')
             ->orderBy('posts.created_at', 'desc')
             ->groupBy('posts.user_id')
             ->select('users.*', 'posts.created_at as postTime')
             ->get();

我只从created_at表中选择posts,但您可以在select中添加更多字段,如:

->select('users.*', 'posts.created_at as postTime', 'posts.updated_at as postUpTime', 'posts.id as pid', 'posts.title')

答案 1 :(得分:0)

我相信你要么必须使用更复杂的usort(),要么可以使用连接,但是使用这种方法,你也会失去Eloquent建立关系的方式。

使用usort() ...

private function cmp($a, $b) 
{
    if($a->posts->created_at == $b->posts->created_at) {
        return 0;
    }
    return (strtotime($a->posts->created_at) < strtotime($b->posts->created_at)) ? -1 : 1;
}

$users = User::with(array('posts' => function($query){
    $query->orderBy('created_at', 'desc')->groupBy('user_id')->first();
}))->get();

$users = usort($users, array($this, 'cmp'));

或者如果您更喜欢使用联接,我认为这应该适合您。

$users = DB::table('posts')
    ->select(DB::raw('MAX(`posts`.`created_at`) AS `created_at`, `user_id`, `users`.*'))
    ->orderBy('posts.created_at', 'desc')
    ->groupBy('posts.user_id')
    ->join('users', 'users.id', '=', 'posts.user_id')
    ->get();