【问题标题】:Laravel eloquent - Eager loading nested relationsLaravel 雄辩 - 渴望加载嵌套关系
【发布时间】:2020-05-10 18:49:54
【问题描述】:

我有以下 3 个表:

  • 帖子
  • 评论
  • 标签

帖子:

    class Post extends Eloquent
    {

        public function comments()
        {
            return $this->hasMany(Comment::class,'post_id','id');
        }

    }

    ** Post data **
    {
       'id' : 1,
       'title' : 'bla bla',
       'created_at: 'some date'
    }

评论:

    class Comment extends Eloquent
    {

        public function comments()
        {
            return $this->belongsTo(Post::class,'id');
        }

        public function tags()
        {
            return $this->hasMany(Tag::class,'id','tags_ids');
        }

    }

** Comments data **

    {
      'id' : 322,
      'active' : true
      'post_id' : 1,
      'created_at: 'some date',
      'tags_ids' : [1,2,3]
    }

标签:

    class Tag extends Eloquent
    {

        public function tags()
        {
            return $this->belongsTo(Comment::class,'tags_ids');
        }

    }

    ** Tags data **
    {
      {'id' : 1,
      'description' : 'some description1'
      },
      {'id' : 2,
      'description' : 'some description2'
      },
      {'id' : 3,
      'description' : 'some description3'
      }
    }

post 表有很多 cmets,cmets 表有很多与之关联的标签。

如何使用预先加载将所有这些表放在一起?

类似:

$post = Post::where('id',1)->with(['comments' => function($q) {
   $q->with('tags');
}])->first();

但是这个查询总是在标签关系中返回空响应。

我做错了什么?

想要的结果是这样的:


{
   'id' : 1,
   'title' : 'bla bla',
   'created_at: 'some date',
   'comments':[{
                  'id' : 322,
                  'active' : true
                  'post_id' : 1,
                  'created_at: 'some date',
                  'tags_ids' : [1,2,3],
                  'tags' : [
                            {'id' : 1,'description' : 'some description1'},
                            {'id' : 2,  'description' : 'some description2'},
                            {'id' : 3,'description' : 'some description3'}
                           ],
              }
             ]
}

你可以看到post里面有cmets,cmets里面也有tags关系。

附:我在我的项目中使用了“jenssegers/laravel-mongodb”包,我试图在没有任何原始表达式的情况下做到这一点。

谢谢。

【问题讨论】:

  • 请添加您的 3 个表结构
  • cmets和tags的关系是1-n?然后标签表中缺少字段comment_id。但是你应该考虑一个 n-m 关系。

标签: php laravel mongodb eloquent eager-loading


【解决方案1】:

你可以使用

$post = Post::where('id',1)->with(['comments.tags'])->first();

它将加载所有 cmets 以及 cmets.tags

参考链接https://laravel.com/docs/6.x/eloquent-relationships 在链接搜索Nested Eager Loading

【讨论】:

    【解决方案2】:

    你错误地定义了你的关系。您的评论模型中有 tags_ids 作为数组,但您的标签需要多对多关系。要实现这一点,您必须定义一个新表comment-tag

    comment-tag
        comment_id - unsined big integer
        tag_id - unsigned big integer
    

    然后在你Comment模型中修改tags这样的关系:

    class Comment extends Model
    {
        /**
         * The tags that belong to the comment.
         */
        public function tags()
        {
            return $this->belongsToMany('App\Tag');
        }
    }
    

    这种关系的倒数是:

    class Tag extends Model
    {
        /**
         * The comments that belong to the tag.
         */
        public function comments()
        {
            return $this->belongsToMany('App\Comment');
        }
    }
    

    然后要急切加载嵌套关系,您可以使用“点”语法:

    $post = Post::with(['comments', 'comments.tags'])->find(1);
    

    有关更多信息,请参阅 Laravel 文档上的 Many-to-Many relationship

    【讨论】:

    • 仍然在标签上返回空响应
    • 哈菲兹感谢您的回复。 Tag 模型中的逆是什么?
    • @Avior 我已将逆向添加到我的帖子中。
    • 如果我不能创建另一个表怎么办?我必须使用评论模型中的标签 ids 列来链接标签和 cmets。我可以有一篇有 30 个 cmets 的帖子,每条评论都有 5 个不同的标签与之关联……我不能在关系上使用 whereIn 之类的东西吗?
    • @Avior 您可以使用查询生成器和whereIn 获取评论的标签,但您无法定义这样的关系
    【解决方案3】:

    更新:您必须修复您的数据库架构

    表结构如下:

    - posts
        - id
        - title
        - ...
    
    - comments
        - id
        - active
        - post_id 
        - created_at
    
    - tags
        - id
        - description
        - comment_id 
        - created_at
    
    // App\Post 
    class Post extends Eloquent 
    {
    
        public function comments()
        {
            return $this->hasMany(Comment::class,'post_id','id');
        }
    
    }
    
    // App\Comment 
    class Comment extends Eloquent 
    {
    
        public function post()
        {
            return $this->belongsTo(Post::class);
        }
    
        public function tags()
        {
            return $this->hasMany(Tag::class);
        }
    
    }
    
    
    //App\Tag    
    class Tag extends Eloquent 
    {
    
        public function comment()
        {
            return $this->belongsTo(Comment::class);
        }
    
    }
    
    
    
    
    //...
    $post = Post::with(['comments', 'comments.tags'])->find(1);
    //...
    

    【讨论】:

    • 虽然关系名称错误,但与查询中未使用的问题无关。即comments->tags 关系的倒数,即tag->commentpost->user,此处未使用。
    • 是的,当然,这是经典的一对多关系
    猜你喜欢
    • 1970-01-01
    • 2015-09-18
    • 2016-08-18
    • 2016-05-31
    • 1970-01-01
    • 1970-01-01
    • 2021-05-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多