Skip to content

Instantly share code, notes, and snippets.

@jpalala
Created November 17, 2024 09:52
Show Gist options
  • Save jpalala/1a82085dce065e60f764490a36f24002 to your computer and use it in GitHub Desktop.
Save jpalala/1a82085dce065e60f764490a36f24002 to your computer and use it in GitHub Desktop.
add tags to post

Yes, you can add tags to blog posts by creating a many-to-many relationship between posts and tags. This requires three tables:

  1. posts: Table to store blog posts.
  2. tags: Table to store tags.
  3. post_tag: Pivot table to associate posts with tags.

Migration Code

1. Create tags Table

Run the following command to create a migration for the tags table:

php artisan make:migration create_tags_table

Then, edit the migration file to include the necessary fields:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateTagsTable extends Migration
{
    public function up(): void
    {
        Schema::create('tags', function (Blueprint $table) {
            $table->id();
            $table->string('name')->unique();
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('tags');
    }
}

2. Create Pivot Table post_tag

Run the following command to create a migration for the pivot table:

php artisan make:migration create_post_tag_table

Edit the generated migration file:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePostTagTable extends Migration
{
    public function up(): void
    {
        Schema::create('post_tag', function (Blueprint $table) {
            $table->id();
            $table->foreignId('post_id')->constrained()->onDelete('cascade');
            $table->foreignId('tag_id')->constrained()->onDelete('cascade');
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('post_tag');
    }
}

Relationships in Models

In Post Model

public function tags()
{
    return $this->belongsToMany(Tag::class, 'post_tag');
}

In Tag Model

public function posts()
{
    return $this->belongsToMany(Post::class, 'post_tag');
}

Example Usage

Attach Tags to a Post

$post = Post::find(1);
$tag = Tag::where('name', 'Laravel')->first();

// Attach a tag
$post->tags()->attach($tag->id);

// Attach multiple tags
$post->tags()->attach([1, 2, 3]);

Detach Tags

$post->tags()->detach($tag->id); // Detach a single tag
$post->tags()->detach();        // Detach all tags

Sync Tags

$post->tags()->sync([1, 2, 3]); // Replace existing tags with these

Add Tags to Blog Post Forms

In the Create and Edit Forms

Add a multi-select field for tags:

<div class="mb-3">
    <label for="tags" class="form-label">Tags</label>
    <select class="form-control" id="tags" name="tags[]" multiple>
        @foreach($tags as $tag)
            <option value="{{ $tag->id }}" 
                {{ isset($post) && $post->tags->contains($tag->id) ? 'selected' : '' }}>
                {{ $tag->name }}
            </option>
        @endforeach
    </select>
</div>

In the Controller

Handle tags in store and update methods:

public function store(Request $request)
{
    $validated = $request->validate([
        'title' => 'required|string|max:255',
        'content' => 'required',
        'tags' => 'array', // Tags validation
        'tags.*' => 'exists:tags,id',
    ]);

    $post = Post::create($validated);
    $post->tags()->sync($request->tags);

    return redirect()->route('posts.index');
}

public function update(Request $request, Post $post)
{
    $validated = $request->validate([
        'title' => 'required|string|max:255',
        'content' => 'required',
        'tags' => 'array',
        'tags.*' => 'exists:tags,id',
    ]);

    $post->update($validated);
    $post->tags()->sync($request->tags);

    return redirect()->route('posts.index');
}

Let me know if you'd like to extend this further!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment