Tutorial Laravel 11, Filament, Spatie, Midtrans Bikin Website Toko Online Sederhana

Membangun sebuah website e-commerce bukan hanya tentang bagaimana menampilkan produk dan transaksi pembelian di sisi pengguna (frontend). Sebuah website e-commerce yang baik juga harus memiliki halaman admin yang terstruktur dan efisien untuk memudahkan pengelolaan produk, pesanan, pelanggan, dan laporan penjualan.

Dalam artikel ini, kita akan membahas bagaimana cara membuat halaman admin beserta Content Management System (CMS) menggunakan Laravel dan Filament.

Pentingnya Halaman Admin yang Terstruktur

Bayangkan Anda memiliki sebuah toko fisik dengan berbagai produk yang dijual. Tanpa sistem manajemen yang baik, Anda akan kesulitan melacak stok barang, pesanan yang masuk, atau bahkan detail pelanggan.

Hal ini sama pentingnya dengan toko online. Halaman admin yang terstruktur ibarat sebuah kantor pusat yang mengelola segala aktivitas di toko tersebut. Melalui halaman ini, kita bisa melakukan hal-hal seperti:

  • Mengelola Produk: Menambahkan, mengubah, atau menghapus produk dengan mudah.
  • Mengelola Pesanan: Melihat detail pesanan yang masuk, status pengiriman, hingga riwayat transaksi.
  • Mengelola Pelanggan: Melihat data pelanggan, riwayat pembelian, dan preferensi mereka.
  • Laporan Penjualan: Melihat data penjualan harian, mingguan, hingga bulanan untuk analisis lebih lanjut.

Dengan halaman admin yang baik, seluruh proses pengelolaan ini bisa dilakukan dengan lebih efisien dan terstruktur. Itulah mengapa penting untuk membangun sistem admin yang user-friendly dan dapat diandalkan.

Laravel dan Filament: Kombinasi yang Tepat untuk Membangun CMS

Laravel adalah framework PHP yang sangat populer di kalangan developer web. Framework ini menyediakan berbagai fitur yang membuat pengembangan website menjadi lebih mudah dan aman. Beberapa fitur penting dari Laravel yang relevan untuk membangun sistem admin adalah:

  • Eloquent ORM: Membuat interaksi dengan database menjadi lebih sederhana dan mudah dipahami. Anda bisa menggunakan Eloquent untuk membuat, membaca, mengubah, dan menghapus data di database dengan sintaks yang mudah dipahami.
  • Middleware: Digunakan untuk memfilter dan memeriksa permintaan HTTP sebelum mencapai aplikasi. Ini sangat berguna untuk mengamankan halaman admin dengan memeriksa apakah pengguna sudah login dan memiliki akses yang tepat.
  • Policy: Memberikan kontrol akses yang lebih rinci untuk setiap tindakan yang dilakukan di aplikasi. Misalnya, hanya pengguna dengan peran 'Admin' yang bisa menambahkan produk baru.

Sementara itu, Filament adalah library yang mempermudah pembuatan dashboard dan halaman admin di Laravel. Filament dilengkapi dengan resource builder yang intuitif, sehingga Anda bisa membuat form, tabel, dan antarmuka admin lainnya dengan cepat tanpa perlu menulis kode dari nol. Berikut beberapa keunggulan Filament:

  • Resource Builder: Dengan fitur ini, Anda bisa membuat halaman admin untuk mengelola data seperti produk, pesanan, atau pelanggan hanya dengan beberapa konfigurasi sederhana.
  • Modular: Filament dirancang secara modular, artinya Anda bisa menambahkan fitur atau modul baru ke dalam dashboard admin Anda dengan mudah.
  • User Interface (UI) yang Intuitif: Filament memberikan UI yang user-friendly dan modern, sehingga mudah digunakan bahkan untuk pengguna yang baru mengenal sistem admin.

Mengapa Laravel dan Filament Cocok untuk E-Commerce?

  1. Keamanan: Laravel dilengkapi dengan fitur seperti CSRF protection, validasi input, dan manajemen sesi yang membantu menjaga keamanan aplikasi e-commerce Anda. Dengan Filament, Anda juga bisa menambahkan level akses yang lebih rinci pada halaman admin.
  2. Kecepatan Pengembangan: Kombinasi Laravel dan Filament memungkinkan pengembangan halaman admin menjadi lebih cepat. Anda tidak perlu membangun dashboard dari nol, cukup gunakan resource builder dari Filament.
  3. Kemudahan Maintenance: Dengan struktur MVC (Model-View-Controller) dari Laravel, Anda bisa memisahkan logika bisnis, tampilan, dan data dengan jelas. Filament membantu memisahkan logika tampilan di halaman admin, sehingga lebih mudah dimaintenance.

Membuat Projek Laravel Terbaru Menggunakan Composer dan Mengatur Koneksi MySQL

Untuk memulai projek Laravel terbaru, kita dapat menggunakan Composer untuk menginstall Laravel beserta dependensinya. Pada langkah-langkah berikut, kita akan belajar cara membuat projek Laravel terbaru menggunakan Composer dan mengatur koneksi MySQL pada file .env.

1. Membuat Projek Laravel dengan Composer

Langkah pertama adalah membuat projek Laravel menggunakan perintah composer create-project. Pastikan Composer sudah terinstall di komputer Anda. Jika belum, silakan download dan install Composer dari situs resmi Composer.

Buka terminal atau command prompt, lalu jalankan perintah berikut:

composer create-project --prefer-dist laravel/laravel nama_projek

Gantilah nama_projek dengan nama projek yang ingin Anda buat. Perintah ini akan mengunduh dan menginstall Laravel beserta dependensi yang diperlukan di folder nama_projek.

2. Mengatur Koneksi Database di File .env

Setelah proses instalasi selesai, masuk ke folder projek yang baru dibuat:

cd nama_projek

Di dalam folder projek tersebut, terdapat file .env yang berfungsi untuk menyimpan konfigurasi environment, termasuk pengaturan koneksi database. Berikut adalah cara mengatur koneksi MySQL di file .env:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=nama_database
DB_USERNAME=root
DB_PASSWORD=kata_sandi

  • DB_CONNECTION: Menentukan jenis database yang digunakan. Dalam contoh ini, kita menggunakan mysql.
  • DB_HOST: Alamat host database. Jika MySQL terinstall secara lokal, gunakan 127.0.0.1.
  • DB_PORT: Port yang digunakan untuk koneksi ke MySQL. Secara default, MySQL menggunakan port 3306.
  • DB_DATABASE: Nama database yang akan digunakan untuk projek Laravel ini. Pastikan database ini sudah dibuat di MySQL.
  • DB_USERNAME: Username yang digunakan untuk mengakses database MySQL.
  • DB_PASSWORD: Password yang digunakan untuk mengakses database MySQL.

Contoh pengaturan .env untuk koneksi ke database MySQL lokal:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_ecommerce
DB_USERNAME=root
DB_PASSWORD=password123

Pastikan untuk mengganti DB_DATABASE, DB_USERNAME, dan DB_PASSWORD sesuai dengan pengaturan di MySQL Anda.

3. Menguji Koneksi Database

Setelah melakukan pengaturan di file .env, langkah selanjutnya adalah menguji koneksi ke database dengan menjalankan migrasi default dari Laravel. Jalankan perintah berikut di terminal:

php artisan migrate

Jika tidak ada error, berarti koneksi ke database berhasil dan tabel-tabel default Laravel berhasil dibuat. Jika terdapat error, periksa kembali pengaturan di file .env dan pastikan database MySQL Anda sudah berjalan.

4. Contoh Kode Lengkap

Berikut adalah contoh file .env lengkap setelah pengaturan koneksi database:

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:.......
APP_DEBUG=true
APP_URL=http://localhost

LOG_CHANNEL=stack
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_ecommerce
DB_USERNAME=root
DB_PASSWORD=password123

BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="[email protected]"
MAIL_FROM_NAME="${APP_NAME}"

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

Dalam contoh ini, konfigurasi yang perlu diperhatikan adalah bagian DB_CONNECTION, DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, dan DB_PASSWORD. Pastikan nilai-nilai ini sesuai dengan pengaturan MySQL Anda.

Membuat File Migration dan Model untuk Tabel E-Commerce di Laravel

Dalam sebuah proyek e-commerce, kita memerlukan beberapa tabel seperti products, categories, customers, dan orders. Setiap tabel ini akan saling berhubungan melalui relasi Eloquent seperti hasMany, belongsTo, dan belongsToMany. Langkah-langkah berikut akan menjelaskan cara membuat file migration dan model untuk setiap tabel, menambahkan properti fillable, serta mengatur hubungan antar tabel menggunakan Artisan command dan metode Eloquent.

Membuat Migration untuk Tabel E-Commerce

Untuk membuat file migration, gunakan perintah Artisan make:migration yang akan membuat file migration baru di dalam folder database/migrations.

Tabel Categories

Mulai dengan membuat tabel categories untuk menyimpan informasi kategori produk:

php artisan make:migration create_categories_table --create=categories

Isi file migration create_categories_table:

Schema::create('categories', function (Blueprint $table) {
    $table->id();
    $table->string('name')->unique(); // Nama kategori unik
    $table->timestamps();
});

Tabel Products

Lanjutkan dengan membuat tabel products untuk menyimpan data produk:

php artisan make:migration create_products_table --create=products

Isi file migration create_products_table:

Schema::create('products', function (Blueprint $table) {
    $table->id();
    $table->string('name'); // Nama produk
    $table->text('description')->nullable(); // Deskripsi produk, bisa null
    $table->decimal('price', 8, 2); // Harga produk
    $table->integer('stock'); // Stok produk
    $table->foreignId('category_id')->constrained()->onDelete('cascade'); // Relasi ke tabel categories
    $table->timestamps();
});

Tabel Customers

Selanjutnya, buat tabel customers untuk menyimpan data pelanggan:

php artisan make:migration create_customers_table --create=customers

Isi file migration create_customers_table:

Schema::create('customers', function (Blueprint $table) {
    $table->id();
    $table->string('name'); // Nama pelanggan
    $table->string('email')->unique(); // Email pelanggan unik
    $table->string('phone'); // Nomor telepon pelanggan
    $table->text('address'); // Alamat pelanggan
    $table->timestamps();
});

Tabel Orders

Terakhir, buat tabel orders untuk menyimpan data pesanan:

php artisan make:migration create_orders_table --create=orders

Isi file migration create_orders_table:

Schema::create('orders', function (Blueprint $table) {
    $table->id();
    $table->foreignId('customer_id')->constrained()->onDelete('cascade'); // Relasi ke tabel customers
    $table->decimal('total_price', 10, 2); // Total harga pesanan
    $table->string('status')->default('pending'); // Status pesanan, default 'pending'
    $table->timestamps();
});

Jalankan semua migration yang telah dibuat dengan perintah:

php artisan migrate

Membuat Model dan Menambahkan Properti Fillable

Setelah membuat migration, kita perlu membuat model untuk setiap tabel. Tambahkan properti fillable pada setiap model untuk mengatur atribut apa saja yang bisa diisi secara massal.

Model Category

Buat model untuk tabel categories:

php artisan make:model Category

Isi file model Category.php:

namespace App\\\\Models;

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

class Category extends Model
{
    use HasFactory;

    protected $fillable = [
        'name', // Atribut yang bisa diisi secara massal
    ];

    public function products()
    {
        return $this->hasMany(Product::class); // Satu kategori memiliki banyak produk
    }
}

Model Product

Buat model untuk tabel products:

php artisan make:model Product

Isi file model Product.php:

namespace App\\\\Models;

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

class Product extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',
        'description',
        'price',
        'stock',
        'category_id'
    ];

    public function category()
    {
        return $this->belongsTo(Category::class); // Produk ini milik satu kategori
    }

    public function orders()
    {
        return $this->belongsToMany(Order::class, 'order_product')->withPivot('quantity'); // Produk bisa ada di banyak pesanan
    }
}

Model Customer

Buat model untuk tabel customers:

php artisan make:model Customer

Isi file model Customer.php:

namespace App\\\\Models;

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

class Customer extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',
        'email',
        'phone',
        'address'
    ];

    public function orders()
    {
        return $this->hasMany(Order::class); // Pelanggan bisa memiliki banyak pesanan
    }
}

Model Order

Buat model untuk tabel orders:

php artisan make:model Order

Isi file model Order.php:

namespace App\\\\Models;

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

class Order extends Model
{
    use HasFactory;

    protected $fillable = [
        'customer_id',
        'total_price',
        'status'
    ];

    public function customer()
    {
        return $this->belongsTo(Customer::class); // Pesanan ini milik satu pelanggan
    }

    public function products()
    {
        return $this->belongsToMany(Product::class, 'order_product')->withPivot('quantity'); // Pesanan bisa memiliki banyak produk
    }
}

Mengatur Relasi Antar Tabel

Berikut adalah penjelasan tentang bagaimana mengatur relasi antar tabel menggunakan Eloquent:

  • Category memiliki relasi hasMany ke Product, artinya satu kategori dapat memiliki banyak produk.
  • Product memiliki relasi belongsTo ke Category, artinya setiap produk hanya dimiliki oleh satu kategori.
  • Customer memiliki relasi hasMany ke Order, artinya satu pelanggan dapat membuat banyak pesanan.
  • Order memiliki relasi belongsTo ke Customer, artinya setiap pesanan hanya dimiliki oleh satu pelanggan.
  • Product dan Order memiliki relasi belongsToMany melalui tabel pivot order_product, artinya satu produk bisa ada di banyak pesanan, dan satu pesanan bisa memiliki banyak produk.

Cara Menginstall Package Filament dan Membuat Akun Admin

Filament adalah paket Laravel yang memudahkan pembuatan dashboard dan Content Management System (CMS) dengan antarmuka yang modern dan fitur-fitur yang lengkap. Berikut adalah langkah-langkah untuk menginstall Filament, membuat akun admin, serta mengonfigurasi user sebagai admin.

Menginstall Package Filament

Mulailah dengan menginstall package Filament menggunakan Composer. Buka terminal atau command prompt di direktori proyek Laravel Anda, kemudian jalankan perintah berikut:

composer require filament/filament

Perintah ini akan mengunduh dan menginstal package Filament beserta semua dependensi yang diperlukan ke dalam proyek Laravel Anda.

Menjalankan Migrasi

Setelah menginstall Filament, Anda perlu menjalankan migrasi untuk membuat tabel yang diperlukan oleh Filament. Tabel ini digunakan untuk menyimpan data user dan manajemen dashboard.

php artisan migrate

Perintah ini akan membuat tabel-tabel yang dibutuhkan Filament, seperti users, password_resets, dan lainnya di dalam database.

Membuat Akun Admin dengan Filament

Filament menyediakan perintah khusus untuk membuat akun admin secara cepat. Gunakan perintah berikut untuk membuat user baru yang akan digunakan sebagai admin:

php artisan make:filament-user

Perintah ini akan meminta Anda untuk memasukkan informasi berikut:

  • Nama user (misalnya Admin User)
  • Alamat email (misalnya [email protected])
  • Kata sandi
  • Opsi untuk menetapkan user sebagai super admin (ketik yes untuk memberikan akses penuh kepada user ini)

Berikut contoh tampilan interaktif di terminal:

Name: Admin User
Email: [email protected]
Password:
Super Admin: yes

Jika Anda memilih yes untuk super admin, user ini akan memiliki semua izin yang tersedia di dashboard Filament.

Konfigurasi Akun Admin

Setelah membuat akun admin, Anda perlu mengatur middleware agar user ini dapat mengakses dashboard Filament. Secara default, Filament menggunakan middleware filament untuk memverifikasi apakah user memiliki izin untuk mengakses dashboard. Pastikan middleware ini sudah dikonfigurasi dengan benar.

Berikut adalah langkah-langkah yang perlu dilakukan untuk mengonfigurasi user sebagai admin:

  • Buka file config/filament.php di proyek Laravel Anda.
  • Temukan bagian auth.guard dan pastikan guard yang digunakan adalah web: 'auth' => [ 'guard' => 'web', ],
  • Temukan bagian auth.providers.users.model dan pastikan model yang digunakan adalah App\\\\Models\\\\User atau model user yang Anda gunakan: 'auth' => [ 'providers' => [ 'users' => [ 'model' => App\\\\Models\\\\User::class, ], ], ],

Pastikan juga bahwa user yang Anda buat memiliki akses ke dashboard Filament. Jika Anda menggunakan Role dan Permission, pastikan bahwa user tersebut memiliki role admin atau izin yang sesuai untuk mengakses halaman dashboard.

Mengakses Dashboard Filament

Setelah melakukan konfigurasi, Anda dapat mengakses dashboard Filament melalui URL berikut:

<http://localhost/admin>

Masukkan email dan password yang telah Anda buat menggunakan perintah make:filament-user. Jika login berhasil, Anda akan masuk ke dashboard Filament yang berisi antarmuka untuk mengelola data.

Membuat Resource untuk CRUD di Filament

Untuk mengelola data dari tabel-tabel yang telah dibuat seperti products, categories, customers, dan orders, kita bisa menggunakan fitur resource dari Filament. Filament memudahkan pembuatan halaman CRUD (Create, Read, Update, Delete) melalui dashboard admin dengan menggunakan command php artisan make:filament-resource. Berikut ini adalah langkah-langkah lengkap untuk membuat resource pada setiap tabel beserta contoh kode konfigurasi fields, forms, dan tables.

Membuat Resource untuk Setiap Tabel

Setiap resource akan merepresentasikan satu tabel di dalam aplikasi e-commerce kita. Gunakan perintah php artisan make:filament-resource untuk membuat resource ini.

Membuat Resource untuk Tabel Categories

php artisan make:filament-resource Category

Resource ini akan menghasilkan beberapa file utama, termasuk file CategoryResource.php yang mengatur bagaimana resource ini ditampilkan di dashboard admin.

Isi file app/Filament/Resources/CategoryResource.php:

namespace App\\\\Filament\\\\Resources;

use App\\\\Filament\\\\Resources\\\\CategoryResource\\\\Pages;
use App\\\\Models\\\\Category;
use Filament\\\\Forms;
use Filament\\\\Resources\\\\Form;
use Filament\\\\Resources\\\\Resource;
use Filament\\\\Resources\\\\Table;
use Filament\\\\Tables;

class CategoryResource extends Resource
{
    protected static ?string $model = Category::class;

    protected static ?string $navigationIcon = 'heroicon-o-tag'; // Ikon untuk menu navigasi

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                Forms\\\\Components\\\\TextInput::make('name')
                    ->required()
                    ->maxLength(255),
            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\\\\Columns\\\\TextColumn::make('id')->sortable(),
                Tables\\\\Columns\\\\TextColumn::make('name')->sortable()->searchable(),
                Tables\\\\Columns\\\\TextColumn::make('created_at')->dateTime(),
            ])
            ->filters([
                //
            ]);
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\\\\ListCategories::route('/'),
            'create' => Pages\\\\CreateCategory::route('/create'),
            'edit' => Pages\\\\EditCategory::route('/{record}/edit'),
        ];
    }
}

Membuat Resource untuk Tabel Products

php artisan make:filament-resource Product

Isi file app/Filament/Resources/ProductResource.php:

namespace App\\\\Filament\\\\Resources;

use App\\\\Filament\\\\Resources\\\\ProductResource\\\\Pages;
use App\\\\Models\\\\Product;
use Filament\\\\Forms;
use Filament\\\\Resources\\\\Form;
use Filament\\\\Resources\\\\Resource;
use Filament\\\\Resources\\\\Table;
use Filament\\\\Tables;

class ProductResource extends Resource
{
    protected static ?string $model = Product::class;

    protected static ?string $navigationIcon = 'heroicon-o-shopping-bag'; // Ikon untuk menu navigasi

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                Forms\\\\Components\\\\TextInput::make('name')
                    ->required()
                    ->maxLength(255),
                Forms\\\\Components\\\\Textarea::make('description')
                    ->maxLength(65535),
                Forms\\\\Components\\\\TextInput::make('price')
                    ->numeric()
                    ->required(),
                Forms\\\\Components\\\\TextInput::make('stock')
                    ->numeric()
                    ->required(),
                Forms\\\\Components\\\\Select::make('category_id')
                    ->relationship('category', 'name')
                    ->required(),
            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\\\\Columns\\\\TextColumn::make('id')->sortable(),
                Tables\\\\Columns\\\\TextColumn::make('name')->sortable()->searchable(),
                Tables\\\\Columns\\\\TextColumn::make('price')->sortable(),
                Tables\\\\Columns\\\\TextColumn::make('stock')->sortable(),
                Tables\\\\Columns\\\\TextColumn::make('category.name')->label('Category'),
                Tables\\\\Columns\\\\TextColumn::make('created_at')->dateTime(),
            ])
            ->filters([
                //
            ]);
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\\\\ListProducts::route('/'),
            'create' => Pages\\\\CreateProduct::route('/create'),
            'edit' => Pages\\\\EditProduct::route('/{record}/edit'),
        ];
    }
}

Membuat Resource untuk Tabel Customers

php artisan make:filament-resource Customer

Isi file app/Filament/Resources/CustomerResource.php:

namespace App\\\\Filament\\\\Resources;

use App\\\\Filament\\\\Resources\\\\CustomerResource\\\\Pages;
use App\\\\Models\\\\Customer;
use Filament\\\\Forms;
use Filament\\\\Resources\\\\Form;
use Filament\\\\Resources\\\\Resource;
use Filament\\\\Resources\\\\Table;
use Filament\\\\Tables;

class CustomerResource extends Resource
{
    protected static ?string $model = Customer::class;

    protected static ?string $navigationIcon = 'heroicon-o-user-group'; // Ikon untuk menu navigasi

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                Forms\\\\Components\\\\TextInput::make('name')
                    ->required()
                    ->maxLength(255),
                Forms\\\\Components\\\\TextInput::make('email')
                    ->email()
                    ->required()
                    ->maxLength(255),
                Forms\\\\Components\\\\TextInput::make('phone')
                    ->tel()
                    ->maxLength(20)
                    ->required(),
                Forms\\\\Components\\\\Textarea::make('address')
                    ->maxLength(65535)
                    ->required(),
            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\\\\Columns\\\\TextColumn::make('id')->sortable(),
                Tables\\\\Columns\\\\TextColumn::make('name')->sortable()->searchable(),
                Tables\\\\Columns\\\\TextColumn::make('email')->sortable()->searchable(),
                Tables\\\\Columns\\\\TextColumn::make('phone')->sortable(),
                Tables\\\\Columns\\\\TextColumn::make('created_at')->dateTime(),
            ])
            ->filters([
                //
            ]);
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\\\\ListCustomers::route('/'),
            'create' => Pages\\\\CreateCustomer::route('/create'),
            'edit' => Pages\\\\EditCustomer::route('/{record}/edit'),
        ];
    }
}

Membuat Resource untuk Tabel Orders

php artisan make:filament-resource Order

Isi file app/Filament/Resources/OrderResource.php:

namespace App\\\\Filament\\\\Resources;

use App\\\\Filament\\\\Resources\\\\OrderResource\\\\Pages;
use App\\\\Models\\\\Order;
use Filament\\\\Forms;
use Filament\\\\Resources\\\\Form;
use Filament\\\\Resources\\\\Resource;
use Filament\\\\Resources\\\\Table;
use Filament\\\\Tables;

class OrderResource extends Resource
{
    protected static ?string $model = Order::class;

    protected static ?string $navigationIcon = 'heroicon-o-shopping-cart'; // Ikon untuk menu navigasi

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                Forms\\\\Components\\\\Select::make('customer_id')
                    ->relationship('customer', 'name')
                    ->required(),
                Forms\\\\Components\\\\TextInput::make('total_price')
                    ->numeric()
                    ->required(),
                Forms\\\\Components\\\\Select::make('status')
                    ->options([
                        'pending' => 'Pending',
                        'completed' => 'Completed',
                        'cancelled' => 'Cancelled',
                    ])
                    ->required(),
            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\\\\Columns\\\\TextColumn::make('id')->sortable(),
                Tables\\\\Columns\\\\TextColumn::make('customer.name')->label('Customer')->sortable(),
                Tables\\\\Columns\\\\TextColumn::make('total_price')->sortable(),
                Tables\\\\Columns\\\\TextColumn::make('status')->sortable(),
                Tables\\\\Columns\\\\TextColumn::make('created_at')->dateTime(),
            ])
            ->filters([
                //
            ]);
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\\\\ListOrders::route('/'),
            'create' => Pages\\\\CreateOrder::route('/create'),
            'edit' => Pages\\\\EditOrder::route('/{record}/edit'),
        ];
    }
}

Mengatur Fields, Forms, dan Tables untuk Setiap Resource

Fields: Digunakan untuk mendefinisikan form input yang akan digunakan ketika menambahkan atau mengedit data. Contohnya adalah Forms\\\\Components\\\\TextInput::make('name') untuk field name.

Forms: Berfungsi untuk mendefinisikan form schema yang ditampilkan pada halaman create dan edit. Contohnya:

Forms\\\\Components\\\\TextInput::make('name')
    ->required()
    ->maxLength(255)

Tables: Digunakan untuk mendefinisikan kolom yang akan ditampilkan pada tabel daftar data. Contohnya:

Tables\\\\Columns\\\\TextColumn::make('name')->sortable()->searchable()

Setiap resource memiliki form dan table yang dikonfigurasikan sesuai kebutuhan untuk mengel

ola data dari tabel yang bersangkutan di halaman admin.

Menambahkan Fitur Authentication Menggunakan Laravel Breeze atau Fortify

Laravel Breeze dan Fortify adalah solusi bawaan Laravel untuk menambahkan fitur autentikasi seperti login, register, dan manajemen pengguna. Keduanya menawarkan cara yang efisien untuk mengamankan akses ke halaman admin.

Berikut adalah langkah-langkah instalasi, konfigurasi, serta penambahan login dan register form untuk memastikan hanya pengguna yang memiliki izin yang dapat mengakses halaman admin.

Menggunakan Laravel Breeze

Instalasi Laravel Breeze

Laravel Breeze menyediakan implementasi autentikasi yang sederhana dan cepat. Untuk menginstal Laravel Breeze, pertama-tama pastikan Anda berada di direktori proyek Laravel, lalu jalankan perintah berikut:

composer require laravel/breeze --dev

Setelah instalasi selesai, jalankan perintah untuk menginstall scaffolding Breeze:

php artisan breeze:install

Perintah ini akan menambahkan file-file yang diperlukan untuk fitur autentikasi seperti halaman login, register, dan dashboard pengguna.

Jalankan Migrasi

Setelah menginstall Breeze, jalankan migrasi untuk membuat tabel users dan password_resets:

php artisan migrate

Install Dependensi Frontend

Laravel Breeze menggunakan Tailwind CSS untuk styling frontend. Jalankan perintah berikut untuk menginstall dependensi frontend dan membangun aplikasi:

npm install && npm run dev

Mengatur Middleware untuk Mengamankan Halaman Admin

Untuk memastikan hanya pengguna yang sudah login yang dapat mengakses halaman admin, gunakan middleware auth pada route admin di file routes/web.php:

Route::middleware(['auth'])->group(function () {
    Route::get('/admin', [AdminController::class, 'index'])->name('admin.index');
    // Route lainnya yang perlu diamankan
});

Dengan middleware auth, Laravel akan memverifikasi apakah pengguna sudah login sebelum mengizinkan akses ke halaman admin.

Konfigurasi Redirect Setelah Login

Untuk mengarahkan pengguna ke halaman admin setelah login, buka file App\\\\Providers\\\\RouteServiceProvider.php dan ubah properti HOME menjadi URL halaman admin:

public const HOME = '/admin';

Menggunakan Laravel Fortify

Laravel Fortify adalah backend authentication scaffolding yang lebih fleksibel. Ini memberikan kontrol penuh untuk mengatur logika autentikasi tanpa dependensi frontend.

Instalasi Laravel Fortify

Untuk menginstall Fortify, jalankan perintah berikut di terminal:

composer require laravel/fortify

Publikasikan file konfigurasi Fortify dengan perintah berikut:

php artisan vendor:publish --provider="Laravel\\\\Fortify\\\\FortifyServiceProvider"

Ini akan menghasilkan file konfigurasi di config/fortify.php.

Aktifkan Fitur Autentikasi

Di dalam file config/fortify.php, aktifkan fitur-fitur yang dibutuhkan seperti login dan register dengan menambahkan:

'features' => [
    Features::registration(),
    Features::resetPasswords(),
    Features::emailVerification(),
    Features::updateProfileInformation(),
    Features::updatePasswords(),
    Features::twoFactorAuthentication(),
],

Jalankan Migrasi

Fortify menggunakan tabel users dan password_resets. Pastikan tabel-tabel ini sudah ada di database dengan menjalankan migrasi:

php artisan migrate

Mengatur View untuk Login dan Register

Untuk menambahkan form login dan register, buat file login.blade.php dan register.blade.php di dalam folder resources/views/auth.

Contoh form login sederhana:

<form method="POST" action="{{ route('login') }}">
    @csrf
    <div>
        <label for="email">Email</label>
        <input id="email" type="email" name="email" required autofocus>
    </div>

    <div>
        <label for="password">Password</label>
        <input id="password" type="password" name="password" required>
    </div>

    <button type="submit">Login</button>
</form>

Contoh form register sederhana:

<form method="POST" action="{{ route('register') }}">
    @csrf
    <div>
        <label for="name">Name</label>
        <input id="name" type="text" name="name" required autofocus>
    </div>

    <div>
        <label for="email">Email</label>
        <input id="email" type="email" name="email" required>
    </div>

    <div>
        <label for="password">Password</label>
        <input id="password" type="password" name="password" required>
    </div>

    <button type="submit">Register</button>
</form>

Menggunakan Middleware untuk Mengamankan Halaman Admin

Tambahkan middleware auth pada route admin di file routes/web.php untuk memastikan hanya pengguna yang sudah login yang dapat mengakses halaman admin:

Route::middleware(['auth'])->group(function () {
    Route::get('/admin', [AdminController::class, 'index'])->name('admin.index');
});

Konfigurasi Guard untuk Admin

Untuk membatasi akses admin dengan lebih spesifik, Anda bisa menambahkan guard baru di file config/auth.php:

'guards' => [
    'admin' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
],

Lalu, pastikan middleware auth:admin digunakan pada route admin:

Route::middleware(['auth:admin'])->group(function () {
    Route::get('/admin', [AdminController::class, 'index'])->name('admin.index');
});

Mengatur Role dan Permission Menggunakan Spatie Laravel Permission

Untuk mengelola akses pengguna dengan lebih terperinci di aplikasi Laravel, kita bisa menggunakan package Spatie Laravel Permission. Package ini memungkinkan kita untuk mengatur role dan permission agar hanya pengguna tertentu yang memiliki akses ke fitur atau halaman tertentu.

Dalam panduan ini, akan dijelaskan cara mengatur role seperti admin, product_manager, sales_staff, dan customer, serta menetapkan izin (permission) untuk masing-masing role beserta contoh koding lengkap.

Instalasi Spatie Laravel Permission

Mulailah dengan menginstal package Spatie Laravel Permission melalui Composer:

composer require spatie/laravel-permission

Setelah terinstal, jalankan perintah untuk mempublikasikan konfigurasi dan migrasi:

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

Perintah ini akan membuat file konfigurasi config/permission.php dan migrasi untuk tabel roles, permissions, dan model_has_roles.

Jalankan migrasi untuk membuat tabel-tabel tersebut:

php artisan migrate

Menambahkan Trait HasRoles ke Model User

Untuk menggunakan fitur role dan permission pada model User, tambahkan trait HasRoles dari package Spatie di model User:

namespace App\\\\Models;

use Illuminate\\\\Foundation\\\\Auth\\\\User as Authenticatable;
use Spatie\\\\Permission\\\\Traits\\\\HasRoles;

class User extends Authenticatable
{
    use HasRoles;

    // properti dan metode lainnya
}

Trait HasRoles ini memungkinkan model User untuk menggunakan metode seperti assignRole, hasRole, givePermissionTo, dan lainnya.

Membuat Role dan Permission

Gunakan seeder untuk membuat role dan permission pertama kali. Buat file seeder dengan perintah:

php artisan make:seeder RolePermissionSeeder

Isi file seeder RolePermissionSeeder.php seperti berikut:

namespace Database\\\\Seeders;

use Illuminate\\\\Database\\\\Seeder;
use Spatie\\\\Permission\\\\Models\\\\Permission;
use Spatie\\\\Permission\\\\Models\\\\Role;

class RolePermissionSeeder extends Seeder
{
    public function run()
    {
        // Membuat permission
        Permission::create(['name' => 'manage products']);
        Permission::create(['name' => 'manage categories']);
        Permission::create(['name' => 'manage orders']);
        Permission::create(['name' => 'view orders']);
        Permission::create(['name' => 'manage users']);

        // Membuat role Admin dan memberikan semua permission
        $admin = Role::create(['name' => 'admin']);
        $admin->givePermissionTo(Permission::all());

        // Membuat role Product Manager dan memberikan permission terkait produk dan kategori
        $productManager = Role::create(['name' => 'product_manager']);
        $productManager->givePermissionTo(['manage products', 'manage categories']);

        // Membuat role Sales Staff dan memberikan permission terkait pesanan
        $salesStaff = Role::create(['name' => 'sales_staff']);
        $salesStaff->givePermissionTo(['view orders', 'manage orders']);

        // Membuat role Customer tanpa permission
        Role::create(['name' => 'customer']);
    }
}

Jalankan seeder untuk memasukkan data role dan permission ke database:

php artisan db:seed --class=RolePermissionSeeder

Seeder ini akan membuat role dan permission yang dibutuhkan serta menghubungkannya.

Mengatur Role pada User

Setelah role dan permission dibuat, Anda dapat memberikan role kepada pengguna. Misalnya, untuk membuat pengguna dengan role admin, gunakan contoh kode berikut di seeder atau di controller:

use App\\\\Models\\\\User;
use Spatie\\\\Permission\\\\Models\\\\Role;

// Misalkan ini adalah user yang sudah terdaftar
$adminUser = User::find(1);
$adminUser->assignRole('admin');

$productManagerUser = User::find(2);
$productManagerUser->assignRole('product_manager');

$salesStaffUser = User::find(3);
$salesStaffUser->assignRole('sales_staff');

Dengan menggunakan metode assignRole, pengguna akan diberikan role yang sesuai.

Middleware untuk Mengamankan Route Berdasarkan Role

Untuk mengamankan route dengan role dan permission, gunakan middleware role atau permission yang disediakan oleh package Spatie.

Contoh untuk mengamankan route agar hanya admin yang bisa mengakses:

Route::group(['middleware' => ['role:admin']], function () {
    Route::get('/admin', [AdminController::class, 'index'])->name('admin.index');
    // Tambahkan route lain yang hanya bisa diakses oleh admin
});

Untuk memberikan akses hanya kepada product_manager atau sales_staff, gunakan:

Route::group(['middleware' => ['role:product_manager|sales_staff']], function () {
    Route::get('/orders', [OrderController::class, 'index'])->name('orders.index');
});

Dengan middleware ini, hanya pengguna dengan role product_manager atau sales_staff yang dapat mengakses halaman daftar pesanan.

Middleware Permission untuk Mengakses Halaman Tertentu

Jika ingin membatasi akses berdasarkan izin (permission), gunakan middleware permission:

Route::group(['middleware' => ['permission:manage products']], function () {
    Route::get('/products', [ProductController::class, 'index'])->name('products.index');
    Route::get('/products/create', [ProductController::class, 'create'])->name('products.create');
    // Route lain yang membutuhkan izin 'manage products'
});

Pengguna dengan izin manage products dapat mengakses halaman ini, tanpa memandang role-nya.

Menampilkan Role dan Permission di Halaman Admin

Untuk memberikan kontrol penuh kepada admin dalam mengelola role dan permission, Anda bisa membuat CRUD untuk role dan permission menggunakan resource Filament. Berikut adalah contoh untuk menampilkan role di halaman admin:

namespace App\\\\Filament\\\\Resources;

use Spatie\\\\Permission\\\\Models\\\\Role;
use Filament\\\\Forms;
use Filament\\\\Resources\\\\Form;
use Filament\\\\Resources\\\\Resource;
use Filament\\\\Resources\\\\Table;
use Filament\\\\Tables;

class RoleResource extends Resource
{
    protected static ?string $model = Role::class;

    protected static ?string $navigationIcon = 'heroicon-o-shield-check';

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                Forms\\\\Components\\\\TextInput::make('name')
                    ->required()
                    ->maxLength(255),
                Forms\\\\Components\\\\Select::make('permissions')
                    ->multiple()
                    ->relationship('permissions', 'name')
                    ->preload(),
            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\\\\Columns\\\\TextColumn::make('name')->sortable(),
                Tables\\\\Columns\\\\TextColumn::make('permissions.name')->label('Permissions')->wrap(),
            ])
            ->filters([
                //
            ]);
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\\\\ListRoles::route('/'),
            'create' => Pages\\\\CreateRole::route('/create'),
            'edit' => Pages\\\\EditRole::route('/{record}/edit'),
        ];
    }
}

Dengan resource ini, admin dapat melihat, menambah, dan mengedit role serta mengatur permission untuk masing-masing role melalui dashboard.

Integrasi Payment Gateway dengan Midtrans untuk Memproses Pembayaran

Integrasi dengan payment gateway seperti Midtrans memungkinkan aplikasi Laravel Anda untuk memproses pembayaran secara langsung dari halaman checkout atau mengelola transaksi melalui halaman admin. Berikut adalah panduan lengkap untuk melakukan integrasi Midtrans, mulai dari instalasi hingga pengelolaan pembayaran melalui halaman admin.

Instalasi SDK Midtrans

Untuk memulai integrasi dengan Midtrans, pertama-tama pastikan package midtrans/midtrans-php sudah terpasang di proyek Laravel Anda. Anda bisa menginstalnya melalui Composer:

composer require midtrans/midtrans-php

Package ini akan membantu dalam berkomunikasi dengan API Midtrans untuk memproses pembayaran.

Konfigurasi Midtrans

Buat file konfigurasi midtrans.php di direktori config untuk menyimpan kredensial dan pengaturan API Midtrans:

return [
    'merchant_id' => env('MIDTRANS_MERCHANT_ID'),
    'client_key' => env('MIDTRANS_CLIENT_KEY'),
    'server_key' => env('MIDTRANS_SERVER_KEY'),
    'is_production' => env('MIDTRANS_PRODUCTION', false),
    'is_sanitized' => env('MIDTRANS_SANITIZED', true),
    'is_3ds' => env('MIDTRANS_3DS', true),
];

Tambahkan variabel konfigurasi berikut ke file .env Anda:

MIDTRANS_MERCHANT_ID=your_merchant_id
MIDTRANS_CLIENT_KEY=your_client_key
MIDTRANS_SERVER_KEY=your_server_key
MIDTRANS_PRODUCTION=false
MIDTRANS_SANITIZED=true
MIDTRANS_3DS=true

Pengaturan ini memastikan bahwa aplikasi Anda dapat berkomunikasi dengan API Midtrans menggunakan kredensial yang benar.

Membuat Fungsi untuk Memproses Pembayaran

Buat sebuah controller baru untuk memproses pembayaran, misalnya PaymentController. Controller ini akan menangani permintaan pembayaran dari halaman checkout dan mengirimkan data ke Midtrans.

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

use Illuminate\\\\Http\\\\Request;
use Midtrans\\\\Config;
use Midtrans\\\\Snap;
use App\\\\Models\\\\Order;

class PaymentController extends Controller
{
    public function processPayment(Request $request)
    {
        // Konfigurasi Midtrans
        Config::$serverKey = config('midtrans.server_key');
        Config::$isProduction = config('midtrans.is_production');
        Config::$isSanitized = config('midtrans.is_sanitized');
        Config::$is3ds = config('midtrans.is_3ds');

        // Mendapatkan data order dari database
        $order = Order::find($request->order_id);

        // Parameter yang dikirim ke Midtrans
        $params = [
            'transaction_details' => [
                'order_id' => $order->id,
                'gross_amount' => $order->total_price,
            ],
            'customer_details' => [
                'first_name' => $order->customer->name,
                'email' => $order->customer->email,
                'phone' => $order->customer->phone,
            ],
            'item_details' => [
                [
                    'id' => 'product-' . $order->product_id,
                    'price' => $order->product->price,
                    'quantity' => $order->quantity,
                    'name' => $order->product->name,
                ],
            ],
        ];

        try {
            // Mendapatkan Snap Token dari Midtrans
            $snapToken = Snap::getSnapToken($params);

            // Menampilkan halaman checkout dengan Snap Token
            return view('payment.checkout', ['snapToken' => $snapToken, 'order' => $order]);
        } catch (\\\\Exception $e) {
            return back()->with('error', 'Gagal memproses pembayaran: ' . $e->getMessage());
        }
    }

    public function handleNotification(Request $request)
    {
        // Logika untuk menangani notifikasi dari Midtrans
    }
}

Pada fungsi processPayment, data order dikirim ke Midtrans untuk mendapatkan Snap Token yang akan digunakan untuk menampilkan halaman pembayaran. Simpan Snap Token ini dan gunakan pada halaman checkout.

Membuat Halaman Checkout

Buat file view resources/views/payment/checkout.blade.php untuk menampilkan halaman checkout dengan widget Snap Midtrans:

@extends('layouts.app')

@section('content')
    <h1>Checkout</h1>
    <p>Order ID: {{ $order->id }}</p>
    <p>Total Pembayaran: Rp {{ number_format($order->total_price, 0, ',', '.') }}</p>

    <button id="pay-button">Bayar Sekarang</button>

    <script type="text/javascript"
        src="<https://app.sandbox.midtrans.com/snap/snap.js>"
        data-client-key="{{ config('midtrans.client_key') }}"></script>
    <script type="text/javascript">
        var payButton = document.getElementById('pay-button');
        payButton.addEventListener('click', function () {
            window.snap.pay('{{ $snapToken }}', {
                onSuccess: function (result) {
                    alert("Pembayaran berhasil!");
                    console.log(result);
                },
                onPending: function (result) {
                    alert("Menunggu pembayaran!");
                    console.log(result);
                },
                onError: function (result) {
                    alert("Pembayaran gagal!");
                    console.log(result);
                },
                onClose: function () {
                    alert('Anda menutup pop-up tanpa menyelesaikan pembayaran');
                }
            });
        });
    </script>
@endsection

Widget Snap dari Midtrans akan membuka pop-up untuk memproses pembayaran ketika tombol "Bayar Sekarang" ditekan. Pop-up ini memungkinkan pengguna untuk menyelesaikan transaksi dengan berbagai metode pembayaran yang disediakan oleh Midtrans.

Mengelola Pembayaran Melalui Halaman Admin

Untuk mengelola pembayaran dari halaman admin, Anda dapat membuat resource baru menggunakan Filament untuk menampilkan data order dan status pembayaran. Misalnya, buat resource OrderResource untuk mengelola pesanan dan statusnya:

namespace App\\\\Filament\\\\Resources;

use App\\\\Models\\\\Order;
use Filament\\\\Resources\\\\Resource;
use Filament\\\\Resources\\\\Form;
use Filament\\\\Resources\\\\Table;
use Filament\\\\Forms;
use Filament\\\\Tables;

class OrderResource extends Resource
{
    protected static ?string $model = Order::class;
    protected static ?string $navigationIcon = 'heroicon-o-clipboard-list';

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                Forms\\\\Components\\\\TextInput::make('id')->disabled(),
                Forms\\\\Components\\\\TextInput::make('customer_name')->disabled(),
                Forms\\\\Components\\\\TextInput::make('status'),
                Forms\\\\Components\\\\TextInput::make('total_price')->disabled(),
                Forms\\\\Components\\\\Textarea::make('note'),
            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\\\\Columns\\\\TextColumn::make('id')->sortable(),
                Tables\\\\Columns\\\\TextColumn::make('customer.name')->label('Customer'),
                Tables\\\\Columns\\\\TextColumn::make('status')->sortable(),
                Tables\\\\Columns\\\\TextColumn::make('total_price')->sortable(),
                Tables\\\\Columns\\\\TextColumn::make('created_at')->dateTime(),
            ])
            ->filters([
                // Tambahkan filter status pembayaran jika diperlukan
            ]);
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\\\\ListOrders::route('/'),
            'edit' => Pages\\\\EditOrder::route('/{record}/edit'),
        ];
    }
}

Dengan resource ini, Anda dapat melihat daftar pesanan, mengubah status pembayaran, dan memberikan catatan pada setiap pesanan melalui halaman admin.

Menangani Notifikasi dari Midtrans

Midtrans menyediakan fitur notifikasi untuk memberi tahu server Anda ketika status transaksi berubah (misalnya, pembayaran berhasil atau gagal). Tambahkan route di file routes/web.php untuk menangani notifikasi ini:

Route::post('/payment/notification', [PaymentController::class, 'handleNotification']);

Di dalam fungsi handleNotification pada PaymentController, Anda bisa menangani notifikasi ini dan memperbarui status pembayaran di database:

public function handleNotification(Request $request)
{
    $notification = $request->all();

    // Logika untuk memperbarui status pesanan berdasarkan notifikasi
    $order = Order::find($notification['order_id']);
    if ($notification['transaction_status'] == 'settlement') {
        $order->status = 'paid';
    } elseif ($notification['transaction_status'] == 'cancel' || $notification['transaction_status'] == 'deny' || $notification['transaction_status'] == 'expire') {
        $order->status = 'failed';
    }
    $order->save();

    return response()->json(['status' => 'success']);
}

Fungsi ini akan menerima notifikasi dari Midtrans dan memperbarui status pesanan di database sesuai dengan status pembayaran yang diterima.

Menambahkan Fitur Notifikasi Email Otomatis di Laravel

Fitur notifikasi email otomatis sangat penting untuk menginformasikan pengguna ketika ada pesanan baru, perubahan status pesanan, atau pengingat untuk menyelesaikan pembayaran. Laravel menyediakan fitur Mailable yang memungkinkan kita untuk mengirim email secara dinamis berdasarkan event tertentu.

Berikut adalah panduan lengkap untuk membuat email template menggunakan Mailable dan mengatur pengiriman email berdasarkan event seperti perubahan status pesanan.

Mengatur Konfigurasi Mail di Laravel

Pastikan konfigurasi mail di Laravel sudah diatur dengan benar di file .env:

MAIL_MAILER=smtp
MAIL_HOST=smtp.example.com
MAIL_PORT=587
[email protected]
MAIL_PASSWORD=your_password
MAIL_ENCRYPTION=tls
[email protected]
MAIL_FROM_NAME="${APP_NAME}"

Jika Anda menggunakan layanan email seperti Gmail, pastikan MAIL_HOST disesuaikan menjadi smtp.gmail.com, dan MAIL_PORT diatur ke 587 atau 465 dengan MAIL_ENCRYPTION yang sesuai (tls atau ssl).

Membuat Email Template dengan Mailable

Laravel menyediakan fitur Mailable untuk membuat template email. Gunakan perintah berikut untuk membuat Mailable:

php artisan make:mail OrderStatusChanged

Ini akan membuat file OrderStatusChanged.php di direktori app/Mail. Buka file tersebut dan atur sesuai kebutuhan:

namespace App\\\\Mail;

use App\\\\Models\\\\Order;
use Illuminate\\\\Bus\\\\Queueable;
use Illuminate\\\\Mail\\\\Mailable;
use Illuminate\\\\Queue\\\\SerializesModels;

class OrderStatusChanged extends Mailable
{
    use Queueable, SerializesModels;

    public $order;

    public function __construct(Order $order)
    {
        $this->order = $order;
    }

    public function build()
    {
        return $this->subject('Status Pesanan Anda Telah Berubah')
                    ->view('emails.order-status')
                    ->with([
                        'order_id' => $this->order->id,
                        'status' => $this->order->status,
                        'customer_name' => $this->order->customer->name,
                    ]);
    }
}

Di sini, kita mengirimkan objek Order ke dalam email template dan menggunakan metode build() untuk menentukan subject email dan view yang akan digunakan.

Membuat View untuk Template Email

Buat file view order-status.blade.php di direktori resources/views/emails:

<!DOCTYPE html>
<html>
<head>
    <title>Status Pesanan Berubah</title>
</head>
<body>
    <h1>Halo, {{ $customer_name }}</h1>
    <p>Pesanan Anda dengan ID <strong>{{ $order_id }}</strong> sekarang berstatus: <strong>{{ $status }}</strong>.</p>
    <p>Terima kasih telah berbelanja di toko kami. Jika ada pertanyaan, jangan ragu untuk menghubungi kami.</p>
    <p>Salam,<br>{{ config('app.name') }}</p>
</body>
</html>

Template ini akan digunakan untuk menampilkan email yang berisi informasi mengenai perubahan status pesanan.

Mengirim Email Berdasarkan Event

Untuk mengirim email berdasarkan event tertentu, misalnya ketika status pesanan berubah, kita bisa menggunakan Event dan Listener di Laravel.

Buat event baru dengan perintah:

php artisan make:event OrderStatusUpdated

Buka file event OrderStatusUpdated.php yang baru dibuat dan tambahkan properti order:

namespace App\\\\Events;

use App\\\\Models\\\\Order;
use Illuminate\\\\Foundation\\\\Events\\\\Dispatchable;
use Illuminate\\\\Queue\\\\SerializesModels;

class OrderStatusUpdated
{
    use Dispatchable, SerializesModels;

    public $order;

    public function __construct(Order $order)
    {
        $this->order = $order;
    }
}

Buat listener untuk menangani event ini dengan perintah:

php artisan make:listener SendOrderStatusChangedEmail

Di dalam listener SendOrderStatusChangedEmail.php, kirim email menggunakan Mailable yang telah dibuat sebelumnya:

namespace App\\\\Listeners;

use App\\\\Events\\\\OrderStatusUpdated;
use App\\\\Mail\\\\OrderStatusChanged;
use Illuminate\\\\Contracts\\\\Queue\\\\ShouldQueue;
use Illuminate\\\\Support\\\\Facades\\\\Mail;

class SendOrderStatusChangedEmail implements ShouldQueue
{
    public function handle(OrderStatusUpdated $event)
    {
        $order = $event->order;

        // Mengirim email menggunakan Mailable
        Mail::to($order->customer->email)->send(new OrderStatusChanged($order));
    }
}

Di listener ini, kita menggunakan facade Mail untuk mengirim email ke customer berdasarkan event OrderStatusUpdated.

Menghubungkan Event dan Listener

Pastikan event dan listener yang telah dibuat dihubungkan dalam file EventServiceProvider.php di app/Providers:

namespace App\\\\Providers;

use App\\\\Events\\\\OrderStatusUpdated;
use App\\\\Listeners\\\\SendOrderStatusChangedEmail;
use Illuminate\\\\Foundation\\\\Support\\\\Providers\\\\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
    protected $listen = [
        OrderStatusUpdated::class => [
            SendOrderStatusChangedEmail::class,
        ],
    ];

    public function boot()
    {
        parent::boot();
    }
}

Dengan konfigurasi ini, setiap kali event OrderStatusUpdated dipanggil, listener SendOrderStatusChangedEmail akan menangani pengiriman email.

Memicu Event saat Status Pesanan Berubah

Di dalam model Order atau di controller tempat Anda mengubah status pesanan, panggil event OrderStatusUpdated setiap kali status pesanan diperbarui:

use App\\\\Events\\\\OrderStatusUpdated;

$order->status = 'shipped';
$order->save();

// Memicu event setelah status pesanan diperbarui
event(new OrderStatusUpdated($order));

Dengan memicu event ini, Laravel akan secara otomatis menjalankan listener yang terhubung dan mengirimkan email notifikasi kepada pengguna.

Mengirim Pengingat untuk Menyelesaikan Pembayaran

Untuk mengirim pengingat kepada pengguna yang belum menyelesaikan pembayaran, buatlah Mailable dan event serupa. Anda dapat menggunakan scheduler untuk memeriksa pesanan yang belum dibayar dan mengirimkan pengingat.

Buat seeder atau command artisan untuk memeriksa pesanan yang belum dibayar:

php artisan make:command SendPaymentReminder

Di dalam command SendPaymentReminder.php, lakukan logika untuk memeriksa pesanan yang belum dibayar:

namespace App\\\\Console\\\\Commands;

use Illuminate\\\\Console\\\\Command;
use App\\\\Models\\\\Order;
use Illuminate\\\\Support\\\\Facades\\\\Mail;
use App\\\\Mail\\\\PaymentReminder;

class SendPaymentReminder extends Command
{
    protected $signature = 'reminder:payment';

    protected $description = 'Kirim pengingat pembayaran kepada pelanggan yang belum menyelesaikan pembayaran';

    public function handle()
    {
        $orders = Order::where('status', 'pending')->get();

        foreach ($orders as $order) {
            Mail::to($order->customer->email)->send(new PaymentReminder($order));
        }

        $this->info('Pengingat pembayaran berhasil dikirim!');
    }
}

Gunakan scheduler di file App\\\\Console\\\\Kernel.php untuk menjalankan perintah ini setiap hari atau sesuai kebutuhan:

protected function schedule(Schedule $schedule)
{
    $schedule->command('reminder:payment')->daily();
}

Ini akan memastikan bahwa pengingat pembayaran dikirimkan secara otomatis kepada pelanggan yang belum menyelesaikan pembayaran setiap hari.

Penutup dan saran dari mentor

Laravel terus menjadi framework yang populer di kalangan developer berkat berbagai update menarik yang memudahkan pengembangan aplikasi web. Dengan fitur-fitur seperti autentikasi yang sederhana, integrasi payment gateway, hingga notifikasi otomatis, Laravel memudahkan developer untuk membangun aplikasi yang robust dan scalable. Kemudahan ini membuat Laravel tetap menjadi pilihan utama untuk banyak proyek pengembangan web.

Untuk terus memperdalam pengetahuan Anda tentang Laravel dan teknologi lainnya, pantau terus website BuildWithAngga. Mereka sering memperbarui kelas gratis dengan studi kasus menarik yang dipandu oleh mentor berpengalaman. Selain itu, Anda juga bisa mendapatkan akses kelas seumur hidup, sehingga dapat belajar kapan saja sesuai kebutuhan. Jangan lewatkan kesempatan untuk mengembangkan skill Anda bersama BuildWithAngga dan jadilah developer yang handal!