【问题标题】:How to list out all items in a nested table in Laravel如何在 Laravel 的嵌套表中列出所有项目
【发布时间】:2013-04-21 21:41:33
【问题描述】:

我正在使用 Laravel 的 Eloquent ORM,但在加载显示项目时遇到了问题。

这里是场景:

  • 用户关注博客
  • 博客有帖子

我有一个名为关系的数据库表,该表用于存储用户 ID 和博客 ID,以显示哪个用户正在关注哪个博客。我有一个用于描述博客的博客表,还有一个用于帖子的表。关系表将是我将用户与博客表连接在一起的数据透视表。现在,我需要在列表中列出用户关注的所有博客中的所有帖子。

这是我的用户模型:

public function following() {
    return $this->has_many_and_belongs_to('Blog', 'relationships', 'user_id', 'blog_id');
}

这是我的博客模型:

public function followers() {
    return $this->has_many_and_belongs_to('User', 'relationships', 'blog_id', 'user_id');
}
public function posts() {
    return $this->has_many('Post');
}

这就是我尝试检索列表中帖子的方式:

$posts = User::with(array('following', 'following.posts'))
            ->find($user->id)
            ->following()
            ->take($count)
            ->get();

这段代码只列出了实际的博客,我需要他们的帖子。

感谢您的帮助,如果您需要更多详细信息,请告诉我。

解决方案:

我稍微修改了下面接受的答案,我决定使用 JOIN 将 SQL 调用量减少到简单的 1 个调用。这里是:

$posts = Post::join('blogs', 'posts.blog_id', '=', 'blogs.id')
    ->join('relationships', 'blogs.id', '=', 'relationships.blog_id')
    ->select('posts.*')
    ->where('relationships.user_id', '=', $user->id)
    ->order_by('posts.id', 'desc')
    ->take($count)
    ->get();

【问题讨论】:

    标签: php activerecord orm laravel laravel-3


    【解决方案1】:

    这是原生 Eloquent 方法无法实现的。但是您可以使用一些 Fluent 方法来连接这些表。例如:

    在此处编辑:我已将即时加载添加到 Post 查询。

    $user = User::find(1);
    $posts = Post::with('blog') // Eager loads the blog this post belongs to
        ->join('blogs', 'blogs.id', '=', 'posts.blog_id')
        ->join('relationships', 'relationships.blog_id', '=', 'blogs.id')
        ->where('relationships.user_id', '=', $user->id)
        ->order_by('posts.id', 'desc') // Latest post first.
        ->limit(10) // Gets last 10 posts
        ->get('posts.*');
    
    foreach ($posts as $post) {
        print($post->title);
    }
    

    例如,如果您还需要该用户关注的所有博客的列表以显示在侧边栏上。你可以 DYI 代替依赖 Eloquent,它应该更快,更可定制。例如:

    $user = User::with('following')->find(1);
    
    // This creates a dictionary for faster performance further ahead
    $dictionary = array();
    foreach ($user->following as $blog) {
        $dictionary[$blog->id] = $blog;
    }
    
    // Retrieves latest 10 posts from these blogs that he follows
    // Obs: Notice the array_keys here
    $posts = Post::where_in('blog_id', array_keys($blog_ids))
        ->order_by('posts.id', 'desc')
        ->limit(10)
        ->get();
    
    // Hydrates all posts with their owning blogs.
    // This avoids loading the blogs twice and has no effect
    // on database records. It's just a helper for views.
    foreach ($posts as $post) {
        $post->relationships['blog'] = $dictionary[$post->blog_id];
    }
    

    正在查看:

    foreach ($user->following as $blog) {
        print($blog->title);
    }
    
    foreach ($posts as $post) {
        print($post->title . ' @'. $post->blog->title);
    }
    

    【讨论】:

    • 急切加载表格怎么样?因为当我急切加载 User::with(array('following', 'following.posts')) 时,数组中的帖子嵌套得更深,我就是无法访问它们。
    • 当你像这样急切地加载时,Eloquent 正在从数据库中查询所有订阅的博客及其帖子,这些帖子可能很快就会变成数千个。如果您希望显示用户订阅的博客中的帖子,比如说像 tumblr 的仪表板,最好的方法是我建议的方法。虽然,您可以像Posts::with('blog') 那样进行反向急切加载。我已经编辑了答案,并就如何解决这个问题提出了一些建议。
    • 谢谢维尼修斯!我尝试了您的两种解决方案,但更喜欢 JOIN 以避免进行多个 SQL 查询。您不需要急切地加载博客关系,因为我们要 JOIN 表。这个解决方案给了我最好的性能。我将您的解决方案的修改版本添加到我的答案中。再次感谢!赢得声誉!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-04
    • 2012-12-02
    • 2011-10-16
    • 2021-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多