BLANTERORIONv101

Laravel Many to Many - Membuat Sistem Tag

12 Agustus 2022

Pada tutorial kali ini, saya akan membahas tentang Laravel Many to Many - Membuat Sistem Tag Pada Postingan. Anda akan melihat bagaimana cara menambahkan tag di postingan dengan menggunakan Laravel many to many.

Untuk membuatnya cukup mudah, Anda bisa mengikuti langkah-langkah di bawah ini sampai selesai.

Langkah 1. Instal Project Laravel

Jika Anda belum memilliki project laravel, maka Anda perlu untuk menginstal aplikasi laravel terlebih dulu, dengan menggunakan perintah di bawah ini:

composer create-project --prefer-dist laravel/laravel example-app

Jika Anda sudah memiliki project dengan aplikasi laravel silahkan lanjut ke langkah kedua.

Langkah 2. Buat Model, Migration & Controller Posts

Pada langkah ini, Anda perlu untuk membuat Model, Migration & Controller. Untuk membuat semua itu Anda bisa menggunakan perintah di bawah ini pada terminal:

php artisan make:model Post -mcr

Pertama, Anda perlu untuk pergi ke direktori database/migrations/create_posts_table.php dan ubah isinya seperti dibawah ini:

public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->string('slug');
            $table->longText('description');
            $table->timestamps();
        });
    }

Langkah 3. Buat Model & Migration Tags

Selanjutnya, Anda perlu untuk membuat model dan migration untuk tags. Anda bisa menjalankan perintah di bawah ini untuk membuatnya.

php artisan make:model Tag -m

Jika sudah menjalankan perintah di atas, silahkan Anda pergi ke direktori database/migrations/create_tags_table.php dan ubah isinya seperti di bawah ini:

public function up()
    {
        Schema::create('tags', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->timestamps();
        });
    }

Langkah 4. Buat Tabel Post Tag Pivot 

Jalankan perintah di bawah ini untuk membuat tabel Post Tag Pivot.

php artisan make:migration CreatePostTagTable

Jika sudah, Anda bisa pergi ke direktori database/migrations/create_post_tag_table.php dan ubah isinya seperti di bawah ini:

public function up()
    {
        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();
        });
    }

Langkah 5. Tambahkan Route

Pada langkah ini, silahkan Anda pergi ke direktori routes/web.php dan tambahkan Route seperti di bawah ini:

Route::resource('posts', PostController::class);

Jangan lupa untuk include File PostController.php

use App\Http\Controllers\PostController;

Langkah 6. Buat Tag Seeder

Selanjutnya, Anda bisa membuat file tag seeder untuk menambahkan data pada tabel tags. Anda bisa jalankan perintah di bawah ini untuk membuatnya.

php artisan make:seeder TagSeeder

Jika sudah, Anda bisa pergi ke direktori database/seeders/TagSeeder.php dan ubah isinya seperti di bawah ini:

<?php

namespace Database\Seeders;

use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\Tag;

class TagSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $tags = [
            [
                'name' => 'Html',
                'created_at' => now(),
                'updated_at' => now(),
            ],
            [
                'name' => 'Css',
                'created_at' => now(),
                'updated_at' => now(),
            ],
            [
                'name' => 'Javascript',
                'created_at' => now(),
                'updated_at' => now(),
            ],
            [
                'name' => 'Bootstrap',
                'created_at' => now(),
                'updated_at' => now(),
            ],
            [
                'name' => 'Css',
                'created_at' => now(),
                'updated_at' => now(),
            ],
            [
                'name' => 'Php',
                'created_at' => now(),
                'updated_at' => now(),
            ],
            [
                'name' => 'Python',
                'created_at' => now(),
                'updated_at' => now(),
            ],
        ];
        Tag::insert($tags);
    }
}

Jika sudah, Anda perlu untuk mengubah file DatabaseSeeder.php seperti di bawah ini, file tersebut masih berada di direktori yang sama.

<?php

namespace Database\Seeders;

// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(TagSeeder::class);
    }
}

Langkah 7. Tambahkan Relasi Many to Many di Model

Di langkah ini, silahkan untuk tambah relasi many to many pada Models/Post.php. Anda bisa isi mengubahnya seperti di bawah ini:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;
    protected $fillable = ['title','slug','description'];

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

Jika sudah menambahkannya pada model Post, sekarang Anda perlu untuk menambahkannya pada model Tag.php seperti di bawah ini:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Tag extends Model
{
    use HasFactory;
    protected $fillable = ['name'];

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

Langkah 8. Post Controller

Pada langkah ini, Anda perlu untuk lampirkan Tag di app/Http/Contollers/PostController.php menggunakan relasi many to many. Silahkan isi seperti kode di bawah ini:

<?php

namespace App\Http\Controllers;

use App\Models\Post;
use App\Models\Tag;
use Illuminate\Support\Str;
use Illuminate\Http\Request;

class PostController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return view('posts.index')->with([
            'posts' => Post::with(['tags'])->latest()->paginate(8),
        ]);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        return view('posts.create')->with([
            'tags' => Tag::all(),
        ]);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $request->validate([
            'title' => 'required|string|max:255',
            'description' =>  'required'
        ]);

        $posts = new Post;
        $posts->title = $request->title;
        $posts->slug = Str::slug($request->title);
        $posts->description = $request->description;
        $posts->save();

        if($request->has('tags'))
        {
            $posts->tags()->attach($request->tags);
        }

        return to_route('posts.index')->with('success','Post Created Successfully');


    }

Langkah 9. Buat File Blade

Selanjutnya, Anda perlu untuk membuat file create.blade.php pada direktori resources/views/posts/create.blade.php dan isi seperti di bawah ini:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap demo</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet" />

  </head>
  <body class="bg-dark">
    <section>
        <div class="container mt-5">
            <h1 class="text-light">Add New Post</h1>
            <a href="{{ route('posts.index') }}" class="btn btn-primary btn-sm mt-5 mb-3">Back</a>
            <div class="card bg-dark shadow">
                <div class="card-body">
                    <form action="{{ route('posts.store') }}" method="POST">
                        @csrf
                        <div class="mb-3">
                          <label for="title" class="form-label text-light">Title</label>
                          <input type="text" class="form-control @error('title') is-invalid @enderror" value="{{ old('title') }}" id="title" name="title" autofocus>
                          @error('title')
                            <span class="invalid-feedback" role="alert">
                                <strong>{{ $message }}</strong>
                            </span>
                            @enderror
                        </div>
                        <div class="mb-3">
                          <label for="tags" class="form-label text-light">Tags</label>
                          <select name="tags[]" class="form-control select2 select2-hidden-accessible @error('tags') is-invalid @enderror" multiple="" data-placeholder="Select a Tag" style="width: 100%;" tabindex="-1" aria-hidden="true">
                            @foreach ($tags as $tag)
                            <option value="{{ $tag->id }}" {{ (collect(old('tags'))->contains($tag->id)) ? 'selected':'' }}>{{ $tag->name }}</option>
                            @endforeach
                        </select>
                            @error('tags')
                            <span class="invalid-feedback" role="alert">
                                <strong>{{ $message }}</strong>
                            </span>
                            @enderror
                        </div>
                        <div class="mb-3">
                            <label for="description" class="form-label text-light">Description</label>
                            <textarea name="description" id="description" class="form-control @error('description') is-invalid @enderror" rows="5">{{ old('description') }}</textarea>
                              @error('description')
                              <span class="invalid-feedback" role="alert">
                                  <strong>{{ $message }}</strong>
                              </span>
                              @enderror
                          </div>
                        <button type="submit" class="btn btn-primary">Save</button>
                      </form>
                </div>
            </div>
        </div>
    </section>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script>
    <script>
     $(document).ready(function() {
        $('.select2').select2({
        closeOnSelect: false
        });
    });
    </script>
  </body>
</html>
Laravel Many to May
Gambar 1. Preview File Create.blade.php

Jika sudah, silahkan buat satu file lagi dengan nama index.blade.php pada direktori yang sama. Anda bisa isi dengan kode di bawah ini:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap demo</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
  </head>
  <body class="bg-dark">
    <section>
        <div class="container mt-5">
            <h1 class="text-light">List Posts</h1>
            <a href="{{ route('posts.create') }}" class="btn btn-primary btn-sm mt-5 mb-3">Add New Posts</a>
            <div class="card bg-dark shadow">
                <div class="card-body">
                    <table class="table table-dark table-striped">
                        <thead>
                            <th>NO</th>
                            <th>Title</th>
                            <th>Tags</th>
                        </thead>
                        <tbody>
                            @foreach ($posts as $no => $result)
                            <tr>
                                <th>{{ $no+1 }}</th>
                                <td>{{ $result->title }}</td>
                                <td>
                                    @foreach ($result->tags as $item)
                                        {{ $item->name }},
                                    @endforeach
                                </td>
                            </tr>
                            @endforeach
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </section>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
  </body>
</html>
Laravel Many to May
Gambar 2. Preview File index.blade.php 

Oke, kurang lebih seperti itu ya. Untuk pembahasan tentang Laravel Many to Many - Membuat Sistem Tag. Jika Anda masih bingung atau terdapat error, silahkan bertanya pada kolom komentar di bawah ini. Terimakasih.

Komentar