The Category functionality is now added
Posted: 2025/03/10
This blog now has Category functionality implemented.
1. Create new Category Model
php artisan make:model Category -mc
2. Update the migration file to create new tables
Schema::create('category_post', function (Blueprint $table) {
$table->id();
$table->foreignIdFor(Post::class)->constrained()->onDelete('cascade');
$table->foreignIdFor(Category::class)->constrained()->onDelete('cascade');
$table->timestamps();
});
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name')
$table->timestamps();
});
3. Migrate new tables
php artisan migrate
4. Define relationship in Post Model
public function categories(): BelongsToMany
{
return $this->belongsToMany(Category::class);
}
5. Define relationship in Category Model
public function posts(): BelongsToMany
{
return $this->belongsToMany(Post::class);
}
Update the PostController to pass all the Categories to the create view
public function create(Post $post) {
$categories = Category::orderBy('name')->get();
return view('post.create', compact('categories'));
}
6. Add Category Selection and Add new Category to the create view
<!-- Categories Section -->
<div class="mb-4">
<label class="block text-gray-700 font-medium mb-2">Categories</label>
<!-- Existing Categories - With Empty State -->
@if(count($categories) > 0)
<div class="mb-3">
<p class="text-sm text-gray-600 mb-2">Select existing categories:</p>
<div class="max-h-40 overflow-y-auto p-3 border border-gray-300 rounded-lg">
@foreach ($categories as $category )
<input type="checkbox" id="{{ $category->id }}" name="categories[]" value="{{ $category->id }}"
{{ (is_array(old('categories')) && in_array($category->id, old('categories'))) ? 'checked' : '' }} >
<label for="{{ $category->id }}">{{ $category->name }}</label><br>
@endforeach
</div>
</div>
@endif
<!-- Add New Categories -->
<div class="{{ count($categories) == 0 ? 'mt-0' : 'mt-4' }}">
<p class="text-sm text-gray-600 mb-2">
@if(count($categories) == 0)
No categories exist yet. Create new categories (comma separated):
@else
Add new categories (comma separated):
@endif
</p>
<input type="text" id="new_categories" name="new_categories" value="{{ old('new_categories') }}"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:outline-none"
placeholder="Technology, Programming, Laravel...">
<p class="text-xs text-gray-500 mt-1">Separate multiple categories with commas</p>
<x-form-error name="new_categories"></x-form-error>
</div>
</div>
8. Update the store function in the PostController to save the categories assigned to post
public function store() {
$validatedAttrs = request()->validate([
'title' => 'required|string|max:255',
'content' => 'required|string|min:20',
'categories' => 'array|nullable',
'new_categories' => 'string|nullable'
]);
// Add the authenticated user's ID
$validatedAttrs['user_id'] = Auth::id();
//dd($validatedAttrs);
// Create post using mass assignment
$post = Post::create($validatedAttrs);
// Attach existing categories
if (!empty($validatedAttrs['categories'])) {
$post->categories()->attach($validatedAttrs['categories']);
}
if (!empty($validatedAttrs['new_categories'])) {
$categoryNames = array_map('trim', explode(',',$validatedAttrs['new_categories']));
foreach ($categoryNames as $categoryName) {
// Check if category already exists or create it
$category = Category::firstOrCreate(['name' => $categoryName]);
//Attach to post if not already attached
if (!$post->categories->contains($category->id)) {
$post->categories()->attach($category->id);
}
}
}
return redirect()->route('blog')->with('success', 'Post created successfully!');
}
9. Repeat the same for the edit view and update view
10. Done
Next: Implement the index view for each Category