Tutorial CRUD Laravel 11, MySQL 8, Breeze, Spatie: Bikin Web Paket Pernikahan

Pada artikel kali ini, kita akan belajar membuat website sederhana untuk paket pernikahan menggunakan Laravel 11, MySQL 8, dan Breeze untuk fitur register dan login. Website ini akan memiliki fitur pencarian dan pemesanan paket pernikahan berdasarkan kategori yang tersedia, melihat detail paket termasuk bonus-bonus, serta melakukan booking dan pembayaran (hanya bisa diakses jika sudah login).

Dalam proses ini, kita juga akan menggunakan Spatie untuk mengelola role dan permission pengguna, sehingga website lebih terstruktur dan aman.

Fitur-Fitur Utama yang Akan Dibangun

  1. Login dan Register: Memungkinkan pengguna untuk mendaftar dan masuk ke website.
  2. Mencari Paket Berdasarkan Kategori: Pengguna bisa mencari paket pernikahan yang sesuai dengan keinginan mereka berdasarkan kategori tertentu.
  3. Melihat Detail Paket: Pengguna bisa melihat deskripsi lengkap paket pernikahan, termasuk fasilitas dan bonus yang disediakan.
  4. Booking dan Pembayaran: Pengguna dapat memilih paket, melakukan booking, dan membayar setelah login.

Sekarang, mari kita mulai dari instalasi alat-alat yang diperlukan seperti PHP, MySQL, Composer, dan MAMP.

Menginstall PHP, MySQL, Composer

Sebelum mulai membangun aplikasi, pastikan bahwa semua alat yang diperlukan seperti PHP, MySQL, dan Composer sudah terinstal di komputer. Di sini, saya akan menjelaskan langkah-langkah instalasinya secara detail.

1. Install PHP

PHP adalah bahasa pemrograman utama yang digunakan oleh Laravel. Untuk menginstall PHP di Windows, unduh PHP dari situs resmi php.net, ekstrak file ke folder pilihan, kemudian tambahkan folder PHP ke PATH di environment variables agar bisa diakses melalui terminal. Setelah itu, cek instalasi dengan mengetik php -v di Command Prompt.

Jika menggunakan macOS, instalasi PHP dapat dilakukan dengan menggunakan Homebrew. Jalankan perintah brew install php di terminal dan cek versi PHP dengan mengetik php -v.

Untuk pengguna Linux seperti Ubuntu, instal PHP dengan menjalankan perintah sudo apt update diikuti dengan sudo apt install php. Setelah itu, cek instalasi dengan php -v.

2. Install MySQL

MySQL digunakan sebagai database untuk menyimpan data pengguna, paket pernikahan, dan transaksi booking. Untuk Windows dan macOS, unduh MySQL dari mysql.com, ikuti langkah-langkah instalasinya, dan pastikan mencatat username serta password root.

Untuk Linux, instal MySQL dengan menjalankan sudo apt update diikuti dengan sudo apt install mysql-server. Setelah instalasi selesai, amankan instalasi dengan menjalankan sudo mysql_secure_installation.

3. Install Composer

Composer digunakan untuk mengelola dependensi proyek Laravel. Untuk Windows, unduh dan install Composer dari getcomposer.org. Pada macOS dan Linux, instal Composer dengan menjalankan perintah berikut di terminal:

curl -sS <https://getcomposer.org/installer> | php
sudo mv composer.phar /usr/local/bin/composer

Cek instalasi dengan mengetik composer di terminal.

4. Install MAMP (Macintosh, Apache, MySQL, PHP)

MAMP adalah perangkat lunak yang menyatukan web server Apache, MySQL, dan PHP ke dalam satu paket instalasi untuk kemudahan pengembangan lokal. Untuk menggunakannya, unduh MAMP dari mamp.info dan instal pada sistem kamu (tersedia untuk macOS dan Windows).

Setelah instalasi selesai, jalankan MAMP dan pastikan server Apache dan MySQL berjalan. Kamu bisa mengakses phpMyAdmin dengan mengetik localhost:8888/phpMyAdmin di browser untuk membuat database baru bernama paket_pernikahan yang akan digunakan oleh Laravel.


1. Membuat Proyek Laravel Terbaru Menggunakan Composer

Untuk membuat project Laravel terbaru, pastikan Composer sudah terinstall. Buka terminal atau Command Prompt dan jalankan perintah berikut untuk membuat project Laravel:

composer create-project --prefer-dist laravel/laravel wedding-package

Setelah project dibuat, masuk ke direktori proyek dengan menjalankan perintah:

cd wedding-package

Menginstall Laravel Breeze

Laravel Breeze menyediakan scaffolding sederhana untuk fitur register dan login. Untuk menginstall Laravel Breeze, jalankan perintah berikut:

composer require laravel/breeze --dev

Selanjutnya, install Breeze dengan menjalankan perintah:

php artisan breeze:install

Lanjutkan dengan menginstall dependensi front-end menggunakan perintah:

npm install && npm run dev

Terakhir, jalankan migrasi untuk membuat tabel pengguna di database:

php artisan migrate

Dengan langkah-langkah ini, fitur login dan register pada website sudah siap digunakan.

2. Membuat File Migration untuk Database

Selanjutnya, kita akan membuat beberapa tabel seperti categories, wedding_packages, wedding_package_bonuses, transactions, dan wedding_package_testimonials.

1. Migration untuk Tabel Categories

Jalankan perintah berikut untuk membuat migration:

php artisan make:migration create_categories_table

Kemudian, buka file migration tersebut dan tambahkan kode berikut:

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

2. Migration untuk Tabel Wedding Packages

Buat migration untuk wedding packages:

php artisan make:migration create_wedding_packages_table

Tambahkan kode berikut di dalam file migration:

public function up()
{
    Schema::create('wedding_packages', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->decimal('price', 10, 2);
        $table->text('description');
        $table->foreignId('category_id')->constrained('categories')->onDelete('cascade');
        $table->timestamps();
    });
}

3. Migration untuk Tabel Wedding Package Bonuses

Buat migration untuk bonus-bonus paket:

php artisan make:migration create_wedding_package_bonuses_table

Tambahkan kode berikut:

public function up()
{
    Schema::create('wedding_package_bonuses', function (Blueprint $table) {
        $table->id();
        $table->string('bonus_name');
        $table->foreignId('wedding_package_id')->constrained('wedding_packages')->onDelete('cascade');
        $table->timestamps();
    });
}

4. Migration untuk Tabel Transactions

Buat migration untuk transaksi:

php artisan make:migration create_transactions_table

Tambahkan kode berikut:

public function up()
{
    Schema::create('transactions', function (Blueprint $table) {
        $table->id();
        $table->foreignId('user_id')->constrained()->onDelete('cascade');
        $table->foreignId('wedding_package_id')->constrained('wedding_packages')->onDelete('cascade');
        $table->decimal('total_price', 10, 2);
        $table->timestamps();
    });
}

5. Migration untuk Tabel Wedding Package Testimonials

Buat migration untuk testimoni paket pernikahan:

php artisan make:migration create_wedding_package_testimonials_table

Tambahkan kode berikut:

public function up()
{
    Schema::create('wedding_package_testimonials', function (Blueprint $table) {
        $table->id();
        $table->text('testimonial');
        $table->foreignId('wedding_package_id')->constrained('wedding_packages')->onDelete('cascade');
        $table->timestamps();
    });
}

Setelah membuat semua migration, jalankan perintah berikut untuk membuat tabel di database:

php artisan migrate

3. Membuat Model dan Mengatur ORM Relationship

Sekarang kita akan membuat model untuk setiap tabel dan mengatur fillable serta hubungan antar tabel.

1. Model Category

Jalankan perintah berikut:

php artisan make:model Category

Di dalam file Category.php, tambahkan properti fillable dan relasi ORM:

class Category extends Model
{
    protected $fillable = ['name'];

    public function weddingPackages()
    {
        return $this->hasMany(WeddingPackage::class);
    }
}

2. Model Wedding Package

Buat model untuk wedding_packages:

php artisan make:model WeddingPackage

Tambahkan fillable dan relasi di WeddingPackage.php:

class WeddingPackage extends Model
{
    protected $fillable = ['name', 'price', 'description', 'category_id'];

    public function category()
    {
        return $this->belongsTo(Category::class);
    }

    public function bonuses()
    {
        return $this->hasMany(WeddingPackageBonus::class);
    }

    public function testimonials()
    {
        return $this->hasMany(WeddingPackageTestimonial::class);
    }
}

3. Model Wedding Package Bonus

Buat model untuk bonus paket:

php artisan make:model WeddingPackageBonus

Tambahkan relasi di dalam file WeddingPackageBonus.php:

class WeddingPackageBonus extends Model
{
    protected $fillable = ['bonus_name', 'wedding_package_id'];

    public function weddingPackage()
    {
        return $this->belongsTo(WeddingPackage::class);
    }
}

4. Model Transaction

Buat model untuk transaksi:

php artisan make:model Transaction

Tambahkan relasi di Transaction.php:

class Transaction extends Model
{
    protected $fillable = ['user_id', 'wedding_package_id', 'total_price'];

    public function weddingPackage()
    {
        return $this->belongsTo(WeddingPackage::class);
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

5. Model Wedding Package Testimonial

Buat model untuk testimoni paket:

php artisan make:model WeddingPackageTestimonial

Tambahkan relasi di dalam file WeddingPackageTestimonial.php:

class WeddingPackageTestimonial extends Model
{
    protected $fillable = ['testimonial', 'wedding_package_id'];

    public function weddingPackage()
    {
        return $this->belongsTo(WeddingPackage::class);
    }
}

4. Menginstall Spatie dan Mengelola Role serta Permission

Spatie digunakan untuk mengatur role dan permission pada website. Untuk menginstall package Spatie, ikuti langkah berikut:

Install Package Spatie

Install Spatie dengan perintah:

composer require spatie/laravel-permission

Publikasikan file konfigurasi dan migration:

php artisan vendor:publish --provider="Spatie\\\\Permission\\\\PermissionServiceProvider"
php artisan migrate

Membuat Seeder Role dan Permission

Buat seeder untuk role dan permission:

php artisan make:seeder RolesAndPermissionsSeeder

Tambahkan kode berikut di dalam seeder:

use Spatie\\\\Permission\\\\Models\\\\Role;
use Spatie\\\\Permission\\\\Models\\\\Permission;

class RolesAndPermissionsSeeder extends Seeder
{
    public function run()
    {
        $admin = Role::create(['name' => 'admin']);
        $user = Role::create(['name' => 'user']);

        Permission::create(['name' => 'manage packages']);
        Permission::create(['name' => 'book packages']);

        $admin->givePermissionTo('manage packages');
        $user->givePermissionTo('book packages');
    }
}

Jalankan seeder:

php artisan db:seed --class=RolesAndPermissionsSeeder

Membuat Akun Admin dan Assign Role Admin

Untuk membuat akun admin, jalankan perintah berikut di tinker:

php artisan tinker

Buat user dan assign role:

$user = User::create([
    'name' => 'Admin',
    'email' => '[email protected]',
    'password' => bcrypt('password'),
]);

$user->assignRole('admin');

5. Mengatur Routing Berdasarkan Role dan Permission

Tambahkan middleware untuk memeriksa role dan permission di route file web.php:

use App\\\\Http\\\\Controllers\\\\WeddingPackageController;

Route::group(['middleware' => ['role:admin']], function ()

 {
    Route::resource('wedding-packages', WeddingPackageController::class);
});

Route::group(['middleware' => ['role:user']], function () {
    Route::get('wedding-packages/{id}', [WeddingPackageController::class, 'show']);
    Route::post('wedding-packages/book', [WeddingPackageController::class, 'book']);
});

Dengan ini, rute wedding-packages hanya bisa diakses oleh admin untuk pengelolaan paket, sedangkan user bisa melihat dan memesan paket.

Membuat File Blade untuk CRUD Wedding Packages Menggunakan Tailwind CDN CSS

Pada bagian ini, kita akan membuat beberapa file Blade yang digunakan untuk fitur CRUD (Create, Read, Update, Delete) pada tabel Wedding Packages. Semua tampilan ini akan menggunakan Tailwind CSS CDN untuk mempermudah styling.

1. Tambahkan Tailwind CDN ke Layout Utama

Pertama, kita perlu menambahkan Tailwind CSS ke dalam layout utama proyek Laravel. Buka atau buat file resources/views/layouts/app.blade.php dan tambahkan CDN Tailwind di bagian <head>:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Wedding Packages</title>
    <link href="<https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css>" rel="stylesheet">
</head>
<body class="bg-gray-100">
    <div class="container mx-auto px-4">
        @yield('content')
    </div>
</body>
</html>

Dengan ini, Tailwind CSS siap digunakan di seluruh tampilan website.

2. Membuat Halaman Index (Daftar Wedding Packages)

Selanjutnya, kita akan membuat file Blade untuk menampilkan daftar wedding packages. Buat file resources/views/wedding_packages/index.blade.php.

@extends('layouts.app')

@section('content')
<div class="flex justify-between items-center my-4">
    <h1 class="text-2xl font-bold">Wedding Packages</h1>
    <a href="{{ route('wedding-packages.create') }}" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Add New Package</a>
</div>

<table class="min-w-full bg-white border">
    <thead>
        <tr class="bg-gray-200">
            <th class="py-2 px-4 border">Name</th>
            <th class="py-2 px-4 border">Price</th>
            <th class="py-2 px-4 border">Category</th>
            <th class="py-2 px-4 border">Actions</th>
        </tr>
    </thead>
    <tbody>
        @foreach ($weddingPackages as $package)
        <tr>
            <td class="py-2 px-4 border">{{ $package->name }}</td>
            <td class="py-2 px-4 border">{{ $package->price }}</td>
            <td class="py-2 px-4 border">{{ $package->category->name }}</td>
            <td class="py-2 px-4 border">
                <a href="{{ route('wedding-packages.edit', $package->id) }}" class="bg-yellow-500 hover:bg-yellow-700 text-white font-bold py-1 px-3 rounded">Edit</a>
                <form action="{{ route('wedding-packages.destroy', $package->id) }}" method="POST" class="inline-block">
                    @csrf
                    @method('DELETE')
                    <button type="submit" class="bg-red-500 hover:bg-red-700 text-white font-bold py-1 px-3 rounded">Delete</button>
                </form>
            </td>
        </tr>
        @endforeach
    </tbody>
</table>
@endsection

3. Membuat Halaman Create (Menambahkan Wedding Package)

Buat file resources/views/wedding_packages/create.blade.php untuk menampilkan form menambah paket pernikahan.

@extends('layouts.app')

@section('content')
<h1 class="text-2xl font-bold my-4">Add New Wedding Package</h1>

<form action="{{ route('wedding-packages.store') }}" method="POST" class="bg-white p-6 rounded-lg shadow-md">
    @csrf
    <div class="mb-4">
        <label class="block text-gray-700">Name:</label>
        <input type="text" name="name" class="w-full px-3 py-2 border rounded-lg" required>
    </div>

    <div class="mb-4">
        <label class="block text-gray-700">Price:</label>
        <input type="text" name="price" class="w-full px-3 py-2 border rounded-lg" required>
    </div>

    <div class="mb-4">
        <label class="block text-gray-700">Category:</label>
        <select name="category_id" class="w-full px-3 py-2 border rounded-lg">
            @foreach ($categories as $category)
                <option value="{{ $category->id }}">{{ $category->name }}</option>
            @endforeach
        </select>
    </div>

    <div class="mb-4">
        <label class="block text-gray-700">Description:</label>
        <textarea name="description" class="w-full px-3 py-2 border rounded-lg" required></textarea>
    </div>

    <button type="submit" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Save Package</button>
</form>
@endsection

4. Membuat Halaman Edit (Mengedit Wedding Package)

Untuk halaman edit, buat file resources/views/wedding_packages/edit.blade.php yang serupa dengan form create, tetapi dengan data paket pernikahan yang telah ada.

@extends('layouts.app')

@section('content')
<h1 class="text-2xl font-bold my-4">Edit Wedding Package</h1>

<form action="{{ route('wedding-packages.update', $package->id) }}" method="POST" class="bg-white p-6 rounded-lg shadow-md">
    @csrf
    @method('PUT')

    <div class="mb-4">
        <label class="block text-gray-700">Name:</label>
        <input type="text" name="name" value="{{ $package->name }}" class="w-full px-3 py-2 border rounded-lg" required>
    </div>

    <div class="mb-4">
        <label class="block text-gray-700">Price:</label>
        <input type="text" name="price" value="{{ $package->price }}" class="w-full px-3 py-2 border rounded-lg" required>
    </div>

    <div class="mb-4">
        <label class="block text-gray-700">Category:</label>
        <select name="category_id" class="w-full px-3 py-2 border rounded-lg">
            @foreach ($categories as $category)
                <option value="{{ $category->id }}" {{ $package->category_id == $category->id ? 'selected' : '' }}>{{ $category->name }}</option>
            @endforeach
        </select>
    </div>

    <div class="mb-4">
        <label class="block text-gray-700">Description:</label>
        <textarea name="description" class="w-full px-3 py-2 border rounded-lg" required>{{ $package->description }}</textarea>
    </div>

    <button type="submit" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Update Package</button>
</form>
@endsection

Membuat File Blade untuk CRUD Wedding Testimonials, Transactions, dan Bonuses Menggunakan Tailwind CDN CSS

Pada bagian ini, kita akan membuat beberapa file Blade untuk mengelola testimoni paket pernikahan, transaksi, dan bonus paket pernikahan. Sama seperti sebelumnya, kita akan menggunakan Tailwind CSS CDN untuk styling halaman.


1. Membuat File Blade untuk CRUD Wedding Testimonials

a. Membuat Halaman Index (Daftar Testimoni)

Buat file resources/views/wedding_testimonials/index.blade.php untuk menampilkan daftar testimoni.

@extends('layouts.app')

@section('content')
<div class="flex justify-between items-center my-4">
    <h1 class="text-2xl font-bold">Wedding Testimonials</h1>
    <a href="{{ route('wedding-testimonials.create') }}" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Add New Testimonial</a>
</div>

<table class="min-w-full bg-white border">
    <thead>
        <tr class="bg-gray-200">
            <th class="py-2 px-4 border">Testimonial</th>
            <th class="py-2 px-4 border">Package</th>
            <th class="py-2 px-4 border">Actions</th>
        </tr>
    </thead>
    <tbody>
        @foreach ($testimonials as $testimonial)
        <tr>
            <td class="py-2 px-4 border">{{ $testimonial->testimonial }}</td>
            <td class="py-2 px-4 border">{{ $testimonial->weddingPackage->name }}</td>
            <td class="py-2 px-4 border">
                <a href="{{ route('wedding-testimonials.edit', $testimonial->id) }}" class="bg-yellow-500 hover:bg-yellow-700 text-white font-bold py-1 px-3 rounded">Edit</a>
                <form action="{{ route('wedding-testimonials.destroy', $testimonial->id) }}" method="POST" class="inline-block">
                    @csrf
                    @method('DELETE')
                    <button type="submit" class="bg-red-500 hover:bg-red-700 text-white font-bold py-1 px-3 rounded">Delete</button>
                </form>
            </td>
        </tr>
        @endforeach
    </tbody>
</table>
@endsection

b. Membuat Halaman Create (Menambahkan Testimoni)

Buat file resources/views/wedding_testimonials/create.blade.php untuk menambahkan testimoni baru.

@extends('layouts.app')

@section('content')
<h1 class="text-2xl font-bold my-4">Add New Wedding Testimonial</h1>

<form action="{{ route('wedding-testimonials.store') }}" method="POST" class="bg-white p-6 rounded-lg shadow-md">
    @csrf
    <div class="mb-4">
        <label class="block text-gray-700">Testimonial:</label>
        <textarea name="testimonial" class="w-full px-3 py-2 border rounded-lg" required></textarea>
    </div>

    <div class="mb-4">
        <label class="block text-gray-700">Wedding Package:</label>
        <select name="wedding_package_id" class="w-full px-3 py-2 border rounded-lg">
            @foreach ($weddingPackages as $package)
                <option value="{{ $package->id }}">{{ $package->name }}</option>
            @endforeach
        </select>
    </div>

    <button type="submit" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Save Testimonial</button>
</form>
@endsection

c. Membuat Halaman Edit (Mengedit Testimoni)

Buat file resources/views/wedding_testimonials/edit.blade.php untuk mengedit testimoni.

@extends('layouts.app')

@section('content')
<h1 class="text-2xl font-bold my-4">Edit Wedding Testimonial</h1>

<form action="{{ route('wedding-testimonials.update', $testimonial->id) }}" method="POST" class="bg-white p-6 rounded-lg shadow-md">
    @csrf
    @method('PUT')

    <div class="mb-4">
        <label class="block text-gray-700">Testimonial:</label>
        <textarea name="testimonial" class="w-full px-3 py-2 border rounded-lg" required>{{ $testimonial->testimonial }}</textarea>
    </div>

    <div class="mb-4">
        <label class="block text-gray-700">Wedding Package:</label>
        <select name="wedding_package_id" class="w-full px-3 py-2 border rounded-lg">
            @foreach ($weddingPackages as $package)
                <option value="{{ $package->id }}" {{ $testimonial->wedding_package_id == $package->id ? 'selected' : '' }}>{{ $package->name }}</option>
            @endforeach
        </select>
    </div>

    <button type="submit" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Update Testimonial</button>
</form>
@endsection


2. Membuat File Blade untuk CRUD Transactions

a. Membuat Halaman Index (Daftar Transaksi)

Buat file resources/views/transactions/index.blade.php untuk menampilkan daftar transaksi.

@extends('layouts.app')

@section('content')
<h1 class="text-2xl font-bold my-4">Transactions</h1>

<table class="min-w-full bg-white border">
    <thead>
        <tr class="bg-gray-200">
            <th class="py-2 px-4 border">User</th>
            <th class="py-2 px-4 border">Wedding Package</th>
            <th class="py-2 px-4 border">Total Price</th>
            <th class="py-2 px-4 border">Actions</th>
        </tr>
    </thead>
    <tbody>
        @foreach ($transactions as $transaction)
        <tr>
            <td class="py-2 px-4 border">{{ $transaction->user->name }}</td>
            <td class="py-2 px-4 border">{{ $transaction->weddingPackage->name }}</td>
            <td class="py-2 px-4 border">{{ $transaction->total_price }}</td>
            <td class="py-2 px-4 border">
                <a href="{{ route('transactions.show', $transaction->id) }}" class="bg-green-500 hover:bg-green-700 text-white font-bold py-1 px-3 rounded">View</a>
            </td>
        </tr>
        @endforeach
    </tbody>
</table>
@endsection

b. Membuat Halaman Detail (Menampilkan Detail Transaksi)

Buat file resources/views/transactions/show.blade.php untuk menampilkan detail transaksi.

@extends('layouts.app')

@section('content')
<h1 class="text-2xl font-bold my-4">Transaction Details</h1>

<div class="bg-white p-6 rounded-lg shadow-md">
    <p class="mb-4"><strong>User:</strong> {{ $transaction->user->name }}</p>
    <p class="mb-4"><strong>Wedding Package:</strong> {{ $transaction->weddingPackage->name }}</p>
    <p class="mb-4"><strong>Total Price:</strong> {{ $transaction->total_price }}</p>
</div>
@endsection


3. Membuat File Blade untuk CRUD Wedding Package Bonuses

a. Membuat Halaman Index (Daftar Bonus)

Buat file resources/views/wedding_bonuses/index.blade.php untuk menampilkan daftar bonus.

@extends('layouts.app')

@section('content')
<div class="flex justify-between items-center my-4">
    <h1 class="text-2xl font-bold">Wedding Package Bonuses</h1>
    <a href="{{ route('wedding-bonuses.create') }}" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Add New Bonus</a>
</div>

<table class="min-w-full bg-white border">
    <thead>
        <tr class="bg-gray-200">
            <th class="py-2 px-4 border">Bonus Name</th>
            <th class="py-2 px-4 border">Package</th>
            <th class="py-2 px-4 border">Actions</th>
        </tr>
    </thead>
    <tbody>
        @foreach ($bonuses as $bonus)
        <tr>
            <td class="py-2 px-4 border">{{ $bonus->bonus_name }}</td>
            <td class="py-2 px-4 border">{{ $bonus->weddingPackage->name }}</td>
            <td class="py-2 px-4 border">
                <a href="{{ route('wedding-bonuses.edit', $bonus->id) }}" class="bg-yellow-500 hover:bg-yellow-700 text-white font-bold py-1 px-3 rounded">Edit</a>
                <form action="{{ route('wedding-bonuses.destroy', $bonus->id) }}" method="POST" class="inline-block">
                    @csrf
                    @method('DELETE')
                    <button type="submit" class="bg-red

-500 hover:bg-red-700 text-white font-bold py-1 px-3 rounded">Delete</button>
                </form>
            </td>
        </tr>
        @endforeach
    </tbody>
</table>
@endsection

b. Membuat Halaman Create (Menambahkan Bonus)

Buat file resources/views/wedding_bonuses/create.blade.php untuk menambahkan bonus baru.

@extends('layouts.app')

@section('content')
<h1 class="text-2xl font-bold my-4">Add New Wedding Package Bonus</h1>

<form action="{{ route('wedding-bonuses.store') }}" method="POST" class="bg-white p-6 rounded-lg shadow-md">
    @csrf
    <div class="mb-4">
        <label class="block text-gray-700">Bonus Name:</label>
        <input type="text" name="bonus_name" class="w-full px-3 py-2 border rounded-lg" required>
    </div>

    <div class="mb-4">
        <label class="block text-gray-700">Wedding Package:</label>
        <select name="wedding_package_id" class="w-full px-3 py-2 border rounded-lg">
            @foreach ($weddingPackages as $package)
                <option value="{{ $package->id }}">{{ $package->name }}</option>
            @endforeach
        </select>
    </div>

    <button type="submit" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Save Bonus</button>
</form>
@endsection


Dengan ini, kita sudah membuat beberapa file Blade untuk mengelola Wedding Testimonials, Transactions, dan Bonuses dengan menggunakan Tailwind CSS CDN. Setiap halaman memiliki tampilan yang responsif dan mudah dipahami.

Membuat Controller untuk Business Logic CRUD dengan Implementasi Role dan Permission pada Wedding Testimonials, Transactions, dan Bonuses

Dalam tutorial ini, kita akan membuat controller untuk Wedding Testimonials, Transactions, dan Wedding Bonuses, sekaligus menerapkan role dan permission menggunakan Spatie Laravel Permission untuk mengatur siapa yang memiliki akses ke berbagai operasi CRUD (Create, Read, Update, Delete). Ini memastikan bahwa hanya pengguna dengan izin tertentu yang dapat melakukan tindakan pada data tersebut.

Berikut adalah langkah-langkahnya:


1. Membuat Controller untuk Wedding Testimonials

Buat controller untuk Wedding Testimonials menggunakan artisan command:

php artisan make:controller WeddingTestimonialController --resource

Logika CRUD di WeddingTestimonialController

Tambahkan logika CRUD berikut di app/Http/Controllers/WeddingTestimonialController.php, dan tambahkan middleware untuk role dan permission di setiap aksi:

<?php

namespace App\\\\Http\\\\Controllers;

use App\\\\Models\\\\WeddingTestimonial;
use App\\\\Models\\\\WeddingPackage;
use Illuminate\\\\Http\\\\Request;

class WeddingTestimonialController extends Controller
{
    public function __construct()
    {
        // Hanya admin yang dapat mengelola CRUD testimonial
        $this->middleware('role:admin')->except(['index']);
        $this->middleware('permission:view testimonials')->only('index');
        $this->middleware('permission:create testimonials')->only(['create', 'store']);
        $this->middleware('permission:edit testimonials')->only(['edit', 'update']);
        $this->middleware('permission:delete testimonials')->only('destroy');
    }

    public function index()
    {
        $testimonials = WeddingTestimonial::with('weddingPackage')->get();
        return view('wedding_testimonials.index', compact('testimonials'));
    }

    public function create()
    {
        $weddingPackages = WeddingPackage::all();
        return view('wedding_testimonials.create', compact('weddingPackages'));
    }

    public function store(Request $request)
    {
        $request->validate([
            'testimonial' => 'required',
            'wedding_package_id' => 'required|exists:wedding_packages,id',
        ]);

        WeddingTestimonial::create($request->all());
        return redirect()->route('wedding-testimonials.index')->with('success', 'Testimonial created successfully.');
    }

    public function edit(WeddingTestimonial $testimonial)
    {
        $weddingPackages = WeddingPackage::all();
        return view('wedding_testimonials.edit', compact('testimonial', 'weddingPackages'));
    }

    public function update(Request $request, WeddingTestimonial $testimonial)
    {
        $request->validate([
            'testimonial' => 'required',
            'wedding_package_id' => 'required|exists:wedding_packages,id',
        ]);

        $testimonial->update($request->all());
        return redirect()->route('wedding-testimonials.index')->with('success', 'Testimonial updated successfully.');
    }

    public function destroy(WeddingTestimonial $testimonial)
    {
        $testimonial->delete();
        return redirect()->route('wedding-testimonials.index')->with('success', 'Testimonial deleted successfully.');
    }
}


2. Membuat Controller untuk Transactions

Buat controller untuk Transactions:

php artisan make:controller TransactionController --resource

Logika CRUD di TransactionController

Tambahkan logika berikut di app/Http/Controllers/TransactionController.php dengan middleware untuk role dan permission:

<?php

namespace App\\\\Http\\\\Controllers;

use App\\\\Models\\\\Transaction;
use App\\\\Models\\\\User;
use App\\\\Models\\\\WeddingPackage;
use Illuminate\\\\Http\\\\Request;

class TransactionController extends Controller
{
    public function __construct()
    {
        // Hanya admin yang dapat mengelola transaksi
        $this->middleware('role:admin')->except(['index', 'show']);
        $this->middleware('permission:view transactions')->only(['index', 'show']);
        $this->middleware('permission:create transactions')->only(['create', 'store']);
        $this->middleware('permission:edit transactions')->only(['edit', 'update']);
        $this->middleware('permission:delete transactions')->only('destroy');
    }

    public function index()
    {
        $transactions = Transaction::with(['user', 'weddingPackage'])->get();
        return view('transactions.index', compact('transactions'));
    }

    public function show(Transaction $transaction)
    {
        return view('transactions.show', compact('transaction'));
    }

    public function create()
    {
        $users = User::all();
        $weddingPackages = WeddingPackage::all();
        return view('transactions.create', compact('users', 'weddingPackages'));
    }

    public function store(Request $request)
    {
        $request->validate([
            'user_id' => 'required|exists:users,id',
            'wedding_package_id' => 'required|exists:wedding_packages,id',
            'total_price' => 'required|numeric',
        ]);

        Transaction::create($request->all());
        return redirect()->route('transactions.index')->with('success', 'Transaction created successfully.');
    }

    public function edit(Transaction $transaction)
    {
        $users = User::all();
        $weddingPackages = WeddingPackage::all();
        return view('transactions.edit', compact('transaction', 'users', 'weddingPackages'));
    }

    public function update(Request $request, Transaction $transaction)
    {
        $request->validate([
            'user_id' => 'required|exists:users,id',
            'wedding_package_id' => 'required|exists:wedding_packages,id',
            'total_price' => 'required|numeric',
        ]);

        $transaction->update($request->all());
        return redirect()->route('transactions.index')->with('success', 'Transaction updated successfully.');
    }

    public function destroy(Transaction $transaction)
    {
        $transaction->delete();
        return redirect()->route('transactions.index')->with('success', 'Transaction deleted successfully.');
    }
}


3. Membuat Controller untuk Wedding Package Bonuses

Buat controller untuk Wedding Package Bonuses:

php artisan make:controller WeddingPackageBonusController --resource

Logika CRUD di WeddingPackageBonusController

Tambahkan logika berikut di app/Http/Controllers/WeddingPackageBonusController.php dengan middleware untuk role dan permission:

<?php

namespace App\\\\Http\\\\Controllers;

use App\\\\Models\\\\WeddingPackageBonus;
use App\\\\Models\\\\WeddingPackage;
use Illuminate\\\\Http\\\\Request;

class WeddingPackageBonusController extends Controller
{
    public function __construct()
    {
        // Hanya admin yang dapat mengelola bonus
        $this->middleware('role:admin')->except(['index']);
        $this->middleware('permission:view bonuses')->only('index');
        $this->middleware('permission:create bonuses')->only(['create', 'store']);
        $this->middleware('permission:edit bonuses')->only(['edit', 'update']);
        $this->middleware('permission:delete bonuses')->only('destroy');
    }

    public function index()
    {
        $bonuses = WeddingPackageBonus::with('weddingPackage')->get();
        return view('wedding_bonuses.index', compact('bonuses'));
    }

    public function create()
    {
        $weddingPackages = WeddingPackage::all();
        return view('wedding_bonuses.create', compact('weddingPackages'));
    }

    public function store(Request $request)
    {
        $request->validate([
            'bonus_name' => 'required',
            'wedding_package_id' => 'required|exists:wedding_packages,id',
        ]);

        WeddingPackageBonus::create($request->all());
        return redirect()->route('wedding-bonuses.index')->with('success', 'Bonus created successfully.');
    }

    public function edit(WeddingPackageBonus $bonus)
    {
        $weddingPackages = WeddingPackage::all();
        return view('wedding_bonuses.edit', compact('bonus', 'weddingPackages'));
    }

    public function update(Request $request, WeddingPackageBonus $bonus)
    {
        $request->validate([
            'bonus_name' => 'required',
            'wedding_package_id' => 'required|exists:wedding_packages,id',
        ]);

        $bonus->update($request->all());
        return redirect()->route('wedding-bonuses.index')->with('success', 'Bonus updated successfully.');
    }

    public function destroy(WeddingPackageBonus $bonus)
    {
        $bonus->delete();
        return redirect()->route('wedding-bonuses.index')->with('success', 'Bonus deleted successfully.');
    }
}


4. Mengatur Routing dengan Role dan Permission

Tambahkan routing untuk setiap resource di routes/web.php dan pastikan hanya pengguna dengan izin yang tepat yang dapat mengakses rute tertentu:

use App\\\\Http\\\\Controllers\\\\WeddingTestimonialController;
use App\\\\Http\\\\Controllers\\\\TransactionController;
use App\\\\Http\\\\Controllers\\\\WeddingPackageBonusController;

Route::middleware(['auth'])->group(function () {
    // Wedding Testimonials
    Route::resource('wedding-testimonials', WeddingTestimonialController::class);

    // Transactions
    Route::resource('transactions', TransactionController::class);

    // Wedding Package Bonuses
    Route::resource('wedding-bonuses', WeddingPackageBonusController::class);
});

Di atas, kita menggunakan middleware 'auth' untuk memastikan semua rute hanya bisa diakses oleh pengguna yang sudah login. Setiap controller telah diatur dengan middleware 'role' dan 'permission' untuk mengatur akses sesuai dengan role dan permission yang telah didefinisikan.


5. Mengatur Role dan Permission dengan Spatie

Pastikan kamu telah menambahkan permission yang relevan untuk setiap resource

. Contoh:

use Spatie\\\\Permission\\\\Models\\\\Permission;
use Spatie\\\\Permission\\\\Models\\\\Role;

// Buat permission dan role
$admin = Role::create(['name' => 'admin']);
Permission::create(['name' => 'view testimonials']);
Permission::create(['name' => 'create testimonials']);
Permission::create(['name' => 'edit testimonials']);
Permission::create(['name' => 'delete testimonials']);

Permission::create(['name' => 'view transactions']);
Permission::create(['name' => 'create transactions']);
Permission::create(['name' => 'edit transactions']);
Permission::create(['name' => 'delete transactions']);

Permission::create(['name' => 'view bonuses']);
Permission::create(['name' => 'create bonuses']);
Permission::create(['name' => 'edit bonuses']);
Permission::create(['name' => 'delete bonuses']);

// Assign permission ke role
$admin->givePermissionTo(Permission::all());

Penutup

Dengan mengikuti tutorial ini, kita telah berhasil membangun aplikasi sederhana untuk mengelola Wedding Testimonials, Transactions, dan Bonuses pada sebuah proyek website paket pernikahan. Tidak hanya membahas logika CRUD (Create, Read, Update, Delete), kita juga telah mengimplementasikan role dan permission menggunakan Spatie Laravel Permission.

Dengan ini, kita bisa memastikan bahwa setiap pengguna hanya bisa melakukan aksi sesuai dengan hak akses yang dimilikinya. Langkah-langkah ini memberikan pondasi yang kuat dalam membangun aplikasi web yang aman dan terstruktur.

10 Summary yang Telah Dipelajari

  1. Membuat Proyek Laravel: Kita belajar cara membuat proyek Laravel baru menggunakan Composer, serta bagaimana menginstal Laravel Breeze untuk fitur autentikasi dasar seperti login dan register.
  2. Membuat File Blade dengan Tailwind CSS: Kita mempelajari cara membuat tampilan untuk fitur CRUD menggunakan Blade dan Tailwind CDN, yang membuat proses styling lebih cepat dan mudah.
  3. Membuat Model dan Migration: Kita membuat beberapa file migration untuk tabel wedding testimonials, transactions, dan wedding bonuses, serta menghubungkannya melalui ORM (Object-Relational Mapping) dengan Eloquent di Laravel.
  4. Membuat CRUD untuk Testimonials: Kita belajar membuat controller WeddingTestimonialController untuk mengelola testimonial dengan fitur CRUD penuh, serta menampilkan data dengan Blade.
  5. Membuat CRUD untuk Transactions: Kita membangun logika CRUD pada transaksi paket pernikahan, termasuk menampilkan daftar transaksi dan detail transaksi setiap user.
  6. Membuat CRUD untuk Bonuses: Kita juga belajar membuat fitur CRUD untuk bonus paket pernikahan, yang memungkinkan admin menambah, mengedit, dan menghapus bonus-bonus yang ada.
  7. Menggunakan Spatie Laravel Permission: Kita mengimplementasikan role dan permission menggunakan package Spatie untuk mengatur hak akses pengguna pada setiap operasi CRUD, memastikan hanya pengguna yang memiliki izin yang tepat yang bisa mengakses fitur tertentu.
  8. Mengatur Middleware untuk Role dan Permission: Kita belajar menggunakan middleware untuk mengontrol akses ke rute dan aksi tertentu berdasarkan role dan permission yang sudah ditentukan.
  9. Menyusun Routing dengan Role dan Permission: Kita menyusun rute untuk setiap resource (testimonials, transactions, bonuses) dan memastikan hanya pengguna yang sudah login dan memiliki izin yang dapat mengakses rute-rute tersebut.
  10. Penerapan Validasi Data: Kita menerapkan validasi pada setiap operasi store dan update untuk memastikan data yang dimasukkan oleh pengguna valid sebelum disimpan ke database.

Penutup

Laravel akan terus menjadi salah satu framework paling populer di kalangan developer karena terus menghadirkan pembaruan dan fitur-fitur menarik yang memudahkan pengembangan aplikasi web. Dengan ekosistem yang kaya, dokumentasi yang lengkap, dan komunitas yang aktif, Laravel memberikan pengalaman pengembangan yang efisien dan menyenangkan bagi developer di berbagai tingkatan.

Pantau terus website BuildWithAngga karena mereka sering mengadakan pembaruan kelas-kelas gratis dengan studi kasus menarik. Selain itu, kamu bisa belajar langsung dari mentor berpengalaman dan mendapatkan akses kelas seumur hidup. Dengan materi yang selalu up-to-date dan studi kasus nyata, ini akan sangat membantu dalam meningkatkan kemampuan coding dan memahami penerapan Laravel dalam proyek-proyek nyata.

Jadi, jangan lewatkan kesempatan untuk terus belajar dan berkembang bersama BuildWithAngga!