39
Show All Posts Associated With a Category in Laravel
Ep#25@Laracasts: Show All Posts Associated With a Category
This post is a part of the Week X of 100DaysOfCode Laravel Challenge series.
In the previous episode we established our first Eloquent relationship between our Post
and Category
models. We showed the associated category name under each post title on our blog listing page. Now it is time to click that category name and the load all the posts associated with that category i.e. filter posts by that category.
So, we add a new route to our web.php
route file
Route::get('/categories/{category}', function (Category $category) {
return view('posts', [
'posts' => $category->posts
]);
});
From our Route-Model binding episode, we remember that the wildcard name and the callback variable name (category
in this example) must match up. From the callback function we return the posts for that particular category $category->posts
. So, let's add the relation to the Category
model as we did for the Post
model in the previous episode.
public function posts() {
return $this->hasMany(Post::class);
}
This time we used the hasMany()
relation as a category may have many posts.
Now that we added the posts()
relation to our category model, let's play with it in the tinker. Boot up tinker php artisan tinker
use App\Models\Category;
$c = Category::first();
$c->posts;
The last command will return the posts associated to the first category.
>>> $c->posts;
=> Illuminate\Database\Eloquent\Collection {#4444
all: [
App\Models\Post {#4496
id: 1,
category_id: 1,
title: "Just a personal post",
slug: "just-a-personal-post",
excerpt: "Lorem ipsum is...",
body: "Lorem ipsum is simply a dummy...",
published_at: null,
created_at: "2021-12-15 16:51:59",
updated_at: "2021-12-15 16:51:59",
},
],
}
>>>
>>>
Now let's update our views so that clicking a category name loads a page listing all the posts of that category only. In the Blade templates, update the category hyperlink to /categories/{{ $post->category->id }}
, we later update it to slug
.
<p><a href="/categories/{{ $post->category->id}}">{{ $post->category->title }}</a></p>
Now from the blog listing page click on a category link. It will load a page like this
In the URL you can see the id of the category. That is because Laravel by default will look for the id
attribute of the model bound to the route. Let's change it to the slug
attribute by mentioning slug
in the wildcard as {category:slug}
.
Route::get('/categories/{category:slug}', function (Category $category) {
return view('posts', [
'posts' => $category->posts
]);
});
And update the views to have the slug
instead of id
in the hyperlink.
<p><a href="/categories/{{ $post->category->slug}}">{{ $post->category->title }}</a></p>
To see the full changelog of this episode added to the Blog Project, see the GitHub commit Ep#25 Show All Posts Associated With a Category
.
39