Laravel – Model Relationship to Itself

Laravel provides a nice and easy way to build model relationship using some methods like hasOne(), hasMany(), belongsTo() and belongsToMany() and each one of these methods are used for different kinds of relationships, for example, hasOne() used for one to one relationship and hasMany() for one to many and so on. These methods let use build a relationship among models. Model relationship is useful for retrieving or saving/updating related models (database records) from or to the database. These relationships allow us to save or select related data to/from database very easily without writing complex queries manually, instead, Laravel’s powerful Eloquent ORM does the job for us using those pre-defined relationship. For example, if we have a table Posts and another table comment for storing comments for each posts using the primary key of posts table in the comments table as a foreign key then it may look something like this

So, comments for each post could be found using the post_id foreign key in the comments table and we can retrieve related comments for a post by joining the two tables using id field from post table and the post_id field from comments table. But, by the help of Eloquent ORM we can easily build this relationship between these tables and can easily retrieve comments for any post from the comments table without writing a single query, just like this

To make this working we just need to declare a relationship using appropriate method in the Post Model like:

That’s all we need to do to build the relationship between posts and comments table, it’s a very simple task in Laravel.

Well, I’m not going to discuss on how to make a relationship for all the relation types and to read more about model relationships visit Laravel website. Instead, I’m going to share an experience of mine where I needed to build a relation to a model itself using it’s own primary key and another field as it’s foreign key.

The situation I had:

I had a posts table and a comments table. Each posts could contain multiple comments and each comment can contain one or more child comments as replies. To achieve this, I made the comment table like this

So post_id is the primary key of posts table as id field in the posts table which was an auto incremented field. So, comments were related with each post using id (PK) from posts table and post_id from comments table as foreign key.

To build the relationship between parent comment and child comments I used comment_parent field in the comments table and stored the comment table’s id (PK) in this field if it was a child of that comment and zero by default for all comments for those which are not a child.

The relationship I used for post and comment:

The relationship for parent and child comments:

This replies() method used to select all the comment replies of a parent comment and I used it in the view like

Here in the replies() method I’ve used hasMany('Comment', 'comment_parent'), this built the relationship to the comment table itself using comment_parent as a foreign key where primary key was the id of this same comment table. This was a solution to my nested commenting system and it was only for a test and it worked. This is a screenshot of the nested comment view:

This was the query to load the post with comments:

The $post variable in where('slug', $post) is the post_slug. I’ve selected post by slug with all the parent comments and loaded replies on per comment loop.

This requires a recursive function and I’ve used one in the view, the loop is done inside that function but I din’t post it here to keep the article small and this article is not about how to implement the thing, instead it’s the idea that I used and shared here. Thanks!

Update (19-04-2014):
This is the recursive helper function that I created to loop all the comments and stored in a helper file:

This is how I called the dumpComments function:

This is the partial comment template:

Note: Too much nesting of comments may cause stackoverfow/maximum level of recursion error.

  • Yah Ya

    tnx for the post, but the code you have mentioned does not print all nested comments, it just prints the comments in 2 level unless u make a recursive function for it.

    • @yah_ya:disqus, You are absolutely right about that, I didn’t post the recursive function that I’ve used because it’s about the idea not the implementation of the whole thing and the way I’ve used the function, I didn’t post it because it requires more code including view files and I tried to keep the article small.

      • Yah Ya

        Yup, tnx for explain 😉 , its better to mention btw , cause i’ve confused about 1 hour on this, how this guy made this workkk!!!

        • @yah_ya:disqus, Just updated the article with some information about the recursive function that I’ve omitted. Thanks!

          • Joaquín Díaz

            May I see the recursive function? I’ve been like 2 ours trying to figure it out… I’m awful at recursive :S

          • Dude @joaqundaz:disqus, it’s a part of a full system that is related with database, alone it won’t work but if you email me on my yahoo account (please find from contact page) then I may send you that function with additional information.

          • fdfvdfvdfv


          • fdfvdfvdfv


  • Heikki Lampinen

    I think the whole idea of the article is the recursive thing and it is missing =/

    • @heikkilampinen:disqus, I’ll add soon, thanks for the feedback 🙂

      • Heikki Lampinen


        • Updated with recursive function and related comment templates.

  • Carlos B

    Is there any posible way to get all this code to study it? I mean, the whole view to see the implementation

    • All the code are given. Email me, I’ll send you the code soon when I become free.

      • Captain

        Pls, i need the code as well.. it will guide me in what am building. where can i get your email ?

  • Thiago Mello


  • And what makes you say that the dumpComments() function is recursive? I don’t see any recursive calls, in there!

  • @kamranahmed_se:disqus, it’s recursive because it’s being called within the views/comment/comment_partial/comment.blade.php and {{ dumpComments($comment->replies) }} is the child process.

    • fdfvdfvdfv


      • fdfvdfvdfv


        • fdfvdfvdfv


  • fdfvdfvdfv


  • Ahmed Medo

    Great Article

  • Check the updated article, kind of revision but clear than this: https://heera.it/laravel-nested-relationship-revised#.V9ntypN94dU

Latest Blog