As you know, in relationships between tables in the database, we usually have 3 types of relationships. These relationships are called one-to-one, one-to-many, and many-to-many relationships.
I have made an article describing the one-to-one relationship, now I will explain the one-to-many relationship. As usual, I will make a small demo to explain what happened to this relationship in the API development. Of course, what I’m about to show is the logic to do some CRUD operations. I have prepared the github project at the bottom of this article and these are the outlines:
- One to Many Relationship
- Laravel Preparation
- Eloquent ORM
- Controller & Routing
Let’s start! In this project, I created 2 new tables with the relationship below.
We will create 2 tables, the articles and comments tables because usually these two objects have one-to-many relationship. An article can have many comments right? But a comment only belongs to one article. That’s why this relationship named one-to-many. Let’s setup the project
I use composer here, so at the command prompt type
composer create-project --prefer-dist laravel/laravel one-to-many
Of course you can create your own project name, but in this example I use one-to-many. If you use XAMPP, don’t forget to start it and modify the database name inside the .env file.
Now we need 2 migrations, let’s setup them.
php artisan make:migration create_articles_table
php artisan make:migratino create_comments_table
There will be 2 new files in the database/migrations folder. First let’s configure the create_articles_table.php first.
Then the next one, open create_comments_table.php
As you can see in the comments table, I set the foreign key for article_id column. This column will refer to the id column on articles table. Don’t forget, if one article is deleted, then all the comments related to that article must be deleted as well. So that’s why I use onCascade(‘delete’) function to represent that behavior.
One more thing, i think it is interesting if each article has a best_comment_id column to represent the best comment of each article. Of course, you don’t need to set the best_comment_id column to be a foreign key, just set it as the bigInteger type to save the comment id and it is a nullable column.
Done! Don’t forget to start your XAMPP (if you use that) and configure your database name in the .env file of your project. Then, run the migration!
php artisan migrate
You know what, the migration function (and the Factory/Faker) has so many useful operations and I think it’s interesting if I make one article to cover this migration commands.
Next thing to do, let’s make 2 models. One for articles and another for comments.
php artisan make:model Article
php artisan make:model Comment
We must configure the relationship between the two tables in this models. This relation has slight differences from a one-to-one relationship, but of course, Laravel makes everything easier with Eloquent ORM.
The models will appear in app/Article.php and app/Comment.php. Let’s open the article model
Then the next one, open comment model
All right! Let’s cover the article model first. In the article model, you will see a new function called comments(). The function is explicitly returning with hasMany(‘app\Comment’) function. Laravel will automatically look for a comment table that has the value of the article_id column the same as the current article id. If in the comments table you don’t have any article_id column, but you specify another name (for example another_column_name) , then you can modify the hasMany function become like this: hasMany(‘app\Comment’,’another_column_name’).
But, again, if you don’t specify the second parameter, Laravel will automatically lookup the article_id column in comments table. The convention is always a singular table name with the ending _id.
What about the comments table? Because a comment always has one relation with the articles table, then we can use the belongsTo(‘app/Article’) method. Laravel will automatically lookup an article that has the same id as in the article_id column. Again, if you don’t use the article_id column name, then you must specify it in the second parameter of belongsTo() function.
Controller & Routing
We need two controllers now, so let’s create them
php artisan make:controller ArticleController
php artisan make:controller CommentController
We will find the new controllers inside app/Http/Controllers. Let setup the ArticleController.php first
Then let’s setup the CommentController.php
Whoa there are so many functions here.These functions give examples of how logic works with this relations. The most important thing is when a user save a new comment. First, let’s look at the CommentController inside the store() function. First, I use some validations here when a user insert a new comment, but that’s optional. Then, we create the new comment object and we save the object with calling the article object. If you notice, I never explicitly set a value for the article_id column, but Laravel will automatically save the value for the article_id column when we call $article->comments()->save($comment) function.
The behavior is same when we are reading the comments data. From the ArticleController, we just need call $article->comments function to show all the comments related to that article. In a reverse, from the CommentController, we just call $comment->article function to find out what article that has this comment. Impressive! Behind the scene, of course Laravel do the rest!
Last step, let’s setup the routing.
It’s done! I hope this article can be your reference for how we can handle a one-to-many relationship with Laravel. Thank you for reading this!
Postman API Collection: https://www.getpostman.com/collections/d0744d52aa0383bc399b