DEV Community

Arif Iqbal
Arif Iqbal

Posted on • Updated on

Your First Eloquent Relationship in Laravel

Ep#24@Laracasts: Your First Eloquent Relationship

This post is a part of the Week X of 100DaysOfCode Laravel Challenge series.

Our next goal is to assign a category to our blog posts in our Blog Project. We show the category name on the blog archive and single post pages under post title.

We already have a posts table for our posts. Now we will need another table for categories. We can make a relationship between the two tables so that each post entry has the category id it is assigned to.

So, we need to generate a migration and a model for the Category. We can generate them in two separate commands

php artisan make:model Category
php artisan make:migration categories
Enter fullscreen mode Exit fullscreen mode

or in one single command

php artisan make:model Category -m
Enter fullscreen mode Exit fullscreen mode

where the -m flag in the command is meant for a migration along with the model.

Now add the fields title and slug to the category schema in the categories migration. And add the category_id as foreign key $table->foreignId("category_id"); to the posts migration. Run your migrations php artisan migrate:fresh. Boot up tinker php artisan tinker and add some records to your categories table.

use App\Models\Category;

$c = new Category;
$c->title = "Personal";
$c->slug = "personal";
Enter fullscreen mode Exit fullscreen mode

Repeat the above commands for two other categories Work and Hobbies.

As we have assigned an empty array to the $guarded property in our Post model, we can create posts using Mass Assignment.

use App\Models\Post;

$post = new Post;
$post->create(["title" => "Just a personal post", "slug" => "just-a-personal-post", "excerpt" => "lorem ipsum is simply....", "body" => "Lorem ipsum is simply a dummy text...", "category_id" => 1]);
Enter fullscreen mode Exit fullscreen mode

Similarly, create some posts for the Work and Hobbies categories by assigning the respective category ids to them.

Now that we have assigned a category id to every post, can we access the category of a post like $post->category? Nope, not yet, because we have not added Eloquent Relationship to our Post model yet. The $post->category will return null instead.

In the Post model, add a method category() and return the appropriate relationship.

public function category() {
        return $this->belongsTo(Category::class);
Enter fullscreen mode Exit fullscreen mode

We used the belongsTo() relation because in our case a category can have many posts but a post is assigned to exactly one category.

How to access a related model?

Now that we have added the Category relation to our Post model, it is time access the related category of a post. A potential confusion here could be trying to access the related model as a method $post->category(), which will return the relation Illuminate\Database\Eloquent\Relations\BelongsTo {#4351} instead of the model instance App\Models\Category. So, access it as a property instead of a method.

use App\Models\Post;

$post = Post::first();
Enter fullscreen mode Exit fullscreen mode

And it will return the category model instance as

>>> $post->category;
=> App\Models\Category {#3560
     id: 1,
     title: "Personal",
     slug: "personal",
     created_at: "2021-12-15 16:44:33",
     updated_at: "2021-12-15 16:44:33",
Enter fullscreen mode Exit fullscreen mode

Now you can access the related category title $post->category->title which will return Personal in the above case.

Update your blade templates to show a the associated category under each post title.

<p><a href="#">{{ $post->category->title }}</a></p>
Enter fullscreen mode Exit fullscreen mode

Here we are introducing a problem called the N+1 problem which we will discuss in another episode. Now visit your blog listing page and you will see the category under post title as

Eloquent Relationship in Laravel

To see all the changes made to the Blog Project, see the GitHub commit Ep#24 Your First Eloquent Relationship

Top comments (0)