This two part tutorial will show you how to create and use Laravel Eloquent relationships. Laravel comes packed with a simple, beautiful ActiveRecord implementation for working with databases. As per the documentation, each database table has a corresponding Model to interact with the table. Eloquent relationships are build on top of this. They serve as a very powerful query builders providing method chaining and querying capabilities.
There are basically three relations:
- One To One – the very basic one. For example, a user has only one profile
- One To Many – in this relationship, a single model owns more than one other model. For example, a user may have many blog posts
- Many To Many – combines the hasOne and hasMany relationships.
More about relationships can be found from the official documentation.
In this tutorial however, we are going to focus on a more complicated scenario. It combines both simple and complex relationships. Take for example a scenario where we have a users table (User Model), posts table (Post Model) and comments table (Comment Model). A user can have one or many posts. A post can also have one or many comments. Simple, straight forward. However, let’s introduce a complication where every post must be reviewed before it’s published. This means, the posts table will have two different columns both pointing to the same column in the users table. So, how do you go about it?
To start, let’s add the following tables to our database:
- Users table – Laravel comes with a migration to create users table. You do not need to add anything
- Posts table – Run the following command on your terminal php artisan make:migration create_posts_table Table names should be the plural of the Model, otherwise you will have to add a table property on the model ( protected $table = ‘table_name’ ). Add the following to your migrations’ up method
Posts table has two foreign keys: posted_by and reviewed_by. Both keys point to id column in users table. More about this will be discussed when creating the models.
- Comments table – Run the following command on your terminal php artisan make:migration create_comments_table Add the following to up method
Once you have edited your migrations, run the command php artisan migrate. You can add dummy data for testing if you wish.
- User model – Laravel comes ready with a user model (app/User.php). Add the following to the model
As introduced earlier, relations are mainly one-to-one, one-to-many and many-to-many. First we define a function ‘posted’ which creates a relation between a post and the user who posted it. This is a one-to-many relationship – one user can have many posts. If we didn’t add the complexion of having reviews, our function would look like this:
Notice the difference between the ‘posted’ and ‘posts’ functions. In the posts method, we don’t define the foreign key. Laravel assumes the foreign key follows the convention of model_id as the foreign key column. In this case, the foreign key in posts table pointing to users table would be user_id. Since this is not the case for our posts table (our foreign key is posted_by) that’s why we have to define the second parameter for the foreign key. The same applies to reviewed method.
The comments function follows the simple scenario. Again this is a one-to-many relationship – one user has many comments. Since the foreign key column in comments table pointing to users table is named user_id, we do not need to define the foreign key parameter in the function.
- Post model – to create a Post model, run the command php artisan make:model Model/Post . I like to keep my models (other than User model) in a separate model folder. If you want to follow the default, then use the command php artisan make:model Post. After the running the command open the file app/Model/Post.php and add the following:
In the User model, we defined ‘posted’ and ‘reviewed’ relationships. We now need to define their reverse relationships. Here we are referring to the user who posted or reviewed a post. Since one user has many posts, then a post belongs to a user. A Post model is owned by a User model. Of course if we had not introduced the reviewing complication, the function would look like this:
Lastly the comments function. Again this is a one-to-many relationship. One post has many comments. Take note the function name is plural. While it will still work perfectly with comment instead of comments, the plural is descriptive – one post has many comments.
- Comment model – run command php artisan make:model Model/Comment and add the following
Here we define the reverse relationship for User and Post model. Since a Comment model is owned by both User and Post model, the two functions define the ownership. Also, the foreign keys in comments table are user_id and post_id meaning we do not need to define the second foreign key parameter. The function name here is singular – one comment belongs to a single user or a single post. In the next part, we shall use the relationships to access data from the database.