Avior
Avior

Reputation: 111

Laravel eloquent - Eager loading nested relations

I have the following 3 tables:

Posts:

    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'
    }

Comments:

    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]
    }

Tags:

    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 table has many comments and comments table has many tags associated with it.

How do i get all this tables together using eager loading?

Something like :

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

but this query always returning empty response in the tags relationship.

What am i doing wrong?

The desired result is something like this:


{
   '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'}
                           ],
              }
             ]
}

You can see that post contains comments inside it and comments contains tags relationship inside it as well.

P.S. I am using the 'jenssegers/laravel-mongodb' package in my project and i am trying to do it without any raw expression.

Thanks.

Upvotes: 0

Views: 2752

Answers (3)

Hafez Divandari
Hafez Divandari

Reputation: 9029

You have defined your relationships wrong. You have tags_ids as array in your comment model but instead you need many-to-many relationships for your tags. To implement this you have to define a new table comment-tag:

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

Then in you Comment model modify tags relationship like this:

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

The inverse of this relationship is:

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

Then to eager load nested relationships, you may use "dot" syntax:

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

See Many-to-Many relationship on Laravel docs for more info.

Upvotes: 2

Foued MOUSSI
Foued MOUSSI

Reputation: 4813

UPDATE: You must fix your db schema

The table structure goes like this:

- 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);
//...

Upvotes: 0

Kamlesh Paul
Kamlesh Paul

Reputation: 12391

you can use

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

it will load all the comments as well as comments.tags

ref link https://laravel.com/docs/6.x/eloquent-relationships in link search Nested Eager Loading

Upvotes: 1

Related Questions