Tutorial Laravel 11 dan Filament Bikin Multi Tenant Projek Apotek Online

Pada tutorial ini, kita akan belajar bagaimana membuat website apotek online dengan sistem multi-tenant menggunakan Laravel 11 dan Filament. Dalam sistem ini, terdapat beberapa user dengan hak akses berbeda, seperti super admin dan doctor, di mana masing-masing memiliki fitur yang sesuai dengan perannya.

Menggunakan Laravel sebagai framework back-end dan Filament sebagai admin panel, kita dapat membangun website apotek online yang scalable, aman, dan mudah dikelola. Laravel menawarkan fitur-fitur yang memudahkan pengembangan, sedangkan Filament mempermudah pembuatan dashboard admin yang intuitif dan user-friendly.

Berikut ini adalah langkah-langkah lengkap dalam membangun projek apotek online multi-tenant ini.

1. Membuat File Model dan Migration Menggunakan Artisan Command

Sebelum memulai pengkodean, kita perlu menyiapkan struktur database yang akan digunakan untuk menyimpan data di aplikasi apotek. Tabel-tabel yang kita perlukan meliputi:

  • Categories: Menyimpan kategori obat (misalnya: antibiotik, vitamin, dll.)
  • Medicines: Menyimpan informasi obat yang tersedia
  • Patients: Menyimpan data pasien yang telah mendaftar
  • Transactions: Menyimpan catatan transaksi pembelian obat
  • Doctors: Menyimpan informasi dokter yang terdaftar di sistem

Untuk membuat model dan migration, kita menggunakan Artisan command dari Laravel. Jalankan perintah berikut di terminal:

php artisan make:model Category -m
php artisan make:model Medicine -m
php artisan make:model Patient -m
php artisan make:model Transaction -m
php artisan make:model Doctor -m

Perintah di atas membuat model beserta file migration untuk masing-masing entitas. Berikut adalah beberapa contoh migration yang harus disesuaikan untuk setiap tabel.

Migration untuk Tabel Categories

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

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

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

Migration untuk Tabel Medicines

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

class CreateMedicinesTable extends Migration
{
    public function up()
    {
        Schema::create('medicines', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->text('description');
            $table->integer('quantity');
            $table->decimal('price', 8, 2);
            $table->foreignId('category_id')->constrained()->onDelete('cascade');
            $table->timestamps();
        });
    }

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

Migration untuk Tabel Patients

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

class CreatePatientsTable extends Migration
{
    public function up()
    {
        Schema::create('patients', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->string('phone_number');
            $table->timestamps();
        });
    }

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

Migration untuk Tabel Transactions

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

class CreateTransactionsTable extends Migration
{
    public function up()
    {
        Schema::create('transactions', function (Blueprint $table) {
            $table->id();
            $table->foreignId('patient_id')->constrained()->onDelete('cascade');
            $table->foreignId('medicine_id')->constrained()->onDelete('cascade');
            $table->integer('quantity');
            $table->decimal('total_price', 8, 2);
            $table->timestamps();
        });
    }

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

Migration untuk Tabel Doctors

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

class CreateDoctorsTable extends Migration
{
    public function up()
    {
        Schema::create('doctors', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->string('phone_number');
            $table->timestamps();
        });
    }

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

Setelah seluruh migration selesai dibuat, jalankan perintah berikut untuk meng-migrate struktur database ke dalam aplikasi:

php artisan migrate

2. Mengisi Mass Assignment dan Mengatur Relationship pada Model

Langkah selanjutnya adalah menambahkan mass assignment dan relationship antar model yang telah kita buat. Dalam Laravel, kita perlu mendefinisikan field apa saja yang bisa diisi secara otomatis melalui mass assignment. Selain itu, kita juga harus mengatur relasi antara tabel yang berhubungan, seperti relasi antara Category dan Medicine, Patient dan Transaction, serta Doctor dan Medicine.

Model Category

namespace App\\\\Models;

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

class Category extends Model
{
    use HasFactory;

    protected $fillable = ['name'];

    public function medicines()
    {
        return $this->hasMany(Medicine::class);
    }
}

Model Medicine

namespace App\\\\Models;

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

class Medicine extends Model
{
    use HasFactory;

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

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

    public function transactions()
    {
        return $this->hasMany(Transaction::class);
    }
}

Model Patient

namespace App\\\\Models;

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

class Patient extends Model
{
    use HasFactory;

    protected $fillable = ['name', 'email', 'phone_number'];

    public function transactions()
    {
        return $this->hasMany(Transaction::class);
    }
}

Model Transaction

namespace App\\\\Models;

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

class Transaction extends Model
{
    use HasFactory;

    protected $fillable = ['patient_id', 'medicine_id', 'quantity', 'total_price'];

    public function patient()
    {
        return $this->belongsTo(Patient::class);
    }

    public function medicine()
    {
        return $this->belongsTo(Medicine::class);
    }
}

Model Doctor

namespace App\\\\Models;

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

class Doctor extends Model
{
    use HasFactory;

    protected $fillable = ['name', 'email', 'phone_number'];

    public function medicines()
    {
        return $this->hasMany(Medicine::class);
    }
}


3. Menginstall Filament dan Membuat Akun Super Admin serta Doctor

Langkah ini akan membahas cara menginstal Filament dan mengelola hak akses untuk dua jenis pengguna, yaitu super admin dan doctor, dengan fitur yang berbeda.

Langkah 1: Menginstal Filament

Pertama, pastikan Anda telah menyelesaikan setup model dan relasi database pada proyek Laravel. Filament akan digunakan untuk membangun admin panel yang intuitif dan efisien untuk mengelola data aplikasi seperti medicines, patients, dan transactions.

Untuk menginstal Filament, jalankan perintah berikut di terminal:

composer require filament/filament

Setelah instalasi selesai, Anda perlu melakukan beberapa konfigurasi dasar pada Filament.

Langkah 2: Mengonfigurasi Filament

Setelah Filament berhasil diinstal, Anda dapat membuat admin panel yang bisa diakses melalui URL khusus, misalnya /admin. Untuk melakukan ini, jalankan perintah berikut:

php artisan make:filament-user

Perintah ini akan membuat user admin baru yang bisa digunakan untuk login ke dashboard Filament. Anda akan diminta mengisi beberapa informasi seperti email, password, dan nama pengguna. Setelah proses ini selesai, user baru tersebut bisa login ke admin panel.

Selain itu, Filament juga memberikan kemudahan untuk membuat custom dashboard, resource management, dan role-based access control (RBAC).

Langkah 3: Menambah Role dan Permission untuk Super Admin dan Doctor

Kita akan menggunakan Spatie Permission package untuk menambahkan role dan permission pada sistem. Untuk menginstalnya, jalankan perintah berikut:

composer require spatie/laravel-permission

Setelah instalasi, publish konfigurasi package ini dengan perintah:

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

Dan jangan lupa untuk menjalankan migrasi:

php artisan migrate

Sekarang, kita siap untuk menambahkan role super admin dan doctor. Pertama, tambahkan HasRoles trait ke dalam model User:

use Spatie\\\\Permission\\\\Traits\\\\HasRoles;

class User extends Authenticatable
{
    use HasRoles;
}

Langkah 4: Membuat Seeder untuk Menambahkan Super Admin dan Doctor

Untuk membuat akun super admin dan doctor, kita akan membuat sebuah seeder. Jalankan perintah berikut untuk membuat file seeder:

php artisan make:seeder RoleSeeder

Di dalam file RoleSeeder.php, tambahkan kode berikut:

namespace Database\\\\Seeders;

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

class RoleSeeder extends Seeder
{
    public function run()
    {
        // Membuat role super admin dan doctor
        $superAdmin = Role::create(['name' => 'super_admin']);
        $doctor = Role::create(['name' => 'doctor']);

        // Membuat user super admin
        $userAdmin = User::create([
            'name' => 'Super Admin',
            'email' => '[email protected]',
            'password' => bcrypt('password'),
        ]);
        $userAdmin->assignRole($superAdmin);

        // Membuat user doctor
        $userDoctor = User::create([
            'name' => 'Doctor',
            'email' => '[email protected]',
            'password' => bcrypt('password'),
        ]);
        $userDoctor->assignRole($doctor);
    }
}

Seeder ini akan membuat dua user, satu untuk super admin dan satu untuk doctor, serta akan langsung memberikan role yang sesuai kepada masing-masing user. Jangan lupa untuk menjalankan seeder:

php artisan db:seed --class=RoleSeeder

Setelah seeder dijalankan, kita akan memiliki dua akun dengan role berbeda yang siap digunakan.

Langkah 5: Membuat Fitur Khusus untuk Setiap Role

Sekarang, kita akan mengatur perbedaan fitur yang bisa diakses oleh masing-masing role. Dalam hal ini, super admin memiliki akses untuk mengelola semua data seperti medicines dan transactions, sedangkan doctor hanya bisa melihat data medicines dan patients.

Untuk mengatur hak akses ini, tambahkan middleware role ke dalam route di file web.php. Berikut contohnya:

use App\\\\Http\\\\Controllers\\\\MedicineController;
use App\\\\Http\\\\Controllers\\\\TransactionController;
use App\\\\Http\\\\Controllers\\\\PatientController;

Route::middleware(['role:super_admin'])->group(function () {
    Route::resource('medicines', MedicineController::class);
    Route::resource('transactions', TransactionController::class);
});

Route::middleware(['role:doctor'])->group(function () {
    Route::get('medicines', [MedicineController::class, 'index'])->name('medicines.index');
    Route::get('patients', [PatientController::class, 'index'])->name('patients.index');
});

Dengan konfigurasi di atas, hanya user dengan role super admin yang bisa mengakses dan mengelola data obat dan transaksi, sementara doctor hanya dapat melihat daftar obat dan pasien.


4. Membuat Navigation Blade untuk Role Super Admin dan Doctor

Selanjutnya, kita perlu membuat navigasi yang menyesuaikan dengan role masing-masing pengguna. Dengan begitu, pengguna hanya melihat menu yang sesuai dengan hak akses mereka.

Di dalam file Blade, kita bisa menambahkan logika untuk memeriksa role user saat ini dan menampilkan menu yang relevan:

<ul>
    @if(auth()->user()->hasRole('super_admin'))
        <li><a href="{{ route('medicines.index') }}">Kelola Obat</a></li>
        <li><a href="{{ route('transactions.index') }}">Kelola Transaksi</a></li>
    @endif

    @if(auth()->user()->hasRole('doctor'))
        <li><a href="{{ route('medicines.index') }}">Lihat Obat</a></li>
        <li><a href="{{ route('patients.index') }}">Lihat Pasien</a></li>
    @endif
</ul>

Dengan kode di atas, ketika user super admin login, mereka akan melihat menu untuk mengelola data obat dan transaksi. Sedangkan doctor hanya akan melihat menu untuk melihat data obat dan pasien.


Menambahkan Fitur Role dan Permission Management pada Dashboard Filament

Setelah kita selesai mengatur role dan permission di aplikasi Laravel, langkah selanjutnya adalah memungkinkan pengguna untuk mengelola roles dan permissions langsung dari dashboard Filament. Ini sangat memudahkan administrator untuk membuat, mengedit, dan menghapus role serta mengatur permissions tanpa harus mengakses kode secara manual.

Langkah 1: Membuat Resource untuk Role dan Permission di Filament

Filament menyediakan cara yang mudah untuk membuat halaman resource yang terhubung dengan model seperti Role dan Permission. Kita akan membuat resource untuk Role dan Permission menggunakan command artisan.

Pertama, buat resource untuk Role:

php artisan make:filament-resource Role

Command di atas akan menghasilkan sebuah resource yang bisa kita gunakan di dashboard Filament. Selanjutnya, buka file resource yang dihasilkan di app/Filament/Resources/RoleResource.php dan sesuaikan dengan menambahkan field yang diperlukan:

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

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

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()
                    ->unique(Role::class, 'name'),
            ]);
    }

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

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

Langkah di atas akan menambahkan kemampuan untuk membuat, mengedit, dan menghapus roles di dalam dashboard Filament.

Sekarang, kita akan melakukan hal yang sama untuk Permission. Jalankan command berikut untuk membuat resource permission:

php artisan make:filament-resource Permission

Kemudian buka file app/Filament/Resources/PermissionResource.php dan sesuaikan dengan menambahkan field seperti yang kita lakukan pada resource Role:

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

use App\\\\Filament\\\\Resources\\\\PermissionResource\\\\Pages;
use Filament\\\\Forms;
use Filament\\\\Tables;
use Spatie\\\\Permission\\\\Models\\\\Permission;
use Filament\\\\Resources\\\\Resource;
use Filament\\\\Resources\\\\Form;
use Filament\\\\Resources\\\\Table;

class PermissionResource extends Resource
{
    protected static ?string $model = Permission::class;

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

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

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

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

Dengan menambahkan resource ini, kita sekarang memiliki halaman untuk membuat, mengedit, dan menghapus permissions di dashboard Filament.

Langkah 2: Menambahkan Menu Navigasi untuk Role dan Permission

Setelah kita membuat resource untuk Role dan Permission, kita juga harus memastikan bahwa mereka muncul di menu navigasi dashboard Filament. Secara default, Filament akan menampilkan resource di sidebar navigasi, tetapi kita bisa mengatur urutannya atau menambahkan ikon khusus agar lebih mudah dikenali.

Jika ingin mengatur navigasi dan menambahkan ikon yang sesuai, buka masing-masing file resource (RoleResource.php dan PermissionResource.php) dan pastikan navigationIcon sudah terisi, seperti contoh berikut:

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

protected static ?string $navigationIcon = 'heroicon-o-key'; // Untuk Permission

Sekarang, ketika Anda login ke dashboard Filament, Anda akan melihat menu Role dan Permission di sidebar. Super admin dapat menambah, mengedit, dan menghapus role serta permission sesuai kebutuhan sistem.

Langkah 3: Mengelola Role dan Permission di Dashboard Filament

Setelah semuanya selesai, Anda dapat mengakses dashboard Filament dan mengelola role serta permission melalui interface yang disediakan. Akses halaman ini melalui URL seperti http://your-app-domain/admin, kemudian login menggunakan akun super admin yang telah dibuat sebelumnya.

Di dalam dashboard, Anda dapat:

  • Membuat role baru dengan memberikan nama role dan menambahkannya ke user.
  • Menambah permission baru, misalnya akses khusus untuk mengelola data transaksi atau akses khusus untuk melihat laporan.
  • Assign role dan permission ke user yang berbeda.

Sebagai contoh, untuk menambahkan permission baru pada sebuah role, Anda bisa membuka halaman Role, pilih salah satu role (misalnya doctor), lalu tambahkan permission seperti view medicines dan view patients. Filament akan secara otomatis menangani relasi antara Role dan Permission di back-end.


Kesimpulan

Dengan menambahkan fitur Role dan Permission pada dashboard Filament, Anda memberikan fleksibilitas kepada admin untuk mengelola hak akses pengguna dengan lebih mudah tanpa harus memodifikasi kode secara manual. Hal ini sangat penting dalam proyek dengan sistem multi-tenant di mana user memiliki peran dan hak akses yang berbeda-beda.

Langkah-langkah di atas meliputi cara menginstal Filament, menambah role dan permission menggunakan Spatie Permission, membuat resource untuk role dan permission di dashboard Filament, serta mengatur navigasi dan fitur untuk mengelola hak akses user. Dengan pendekatan ini, aplikasi apotek online Anda akan memiliki kontrol penuh atas manajemen user dan fitur yang dapat diakses oleh mereka.

Penutup

Laravel adalah framework yang sangat cocok dipelajari, terutama bagi pengembang web yang ingin membangun aplikasi yang scalable, aman, dan mudah dikelola. Dengan popularitas yang terus meningkat selama beberapa tahun terakhir, Laravel akan tetap menjadi pilihan utama dalam pengembangan aplikasi web, baik untuk proyek kecil maupun besar. Ditambah dengan ekosistem yang terus berkembang, Laravel menawarkan banyak kemudahan dan dukungan komunitas yang luas.

Bagi Anda yang sedang mengerjakan proyek skripsi atau sedang mempersiapkan diri untuk menjadi developer web profesional, belajar Laravel bersama BuildWithAngga adalah pilihan yang tepat. Di sini, Anda akan belajar dari mentor expert dan berpengalaman yang akan membantu Anda menguasai Laravel dari dasar hingga tingkat lanjut. Anda juga mendapatkan akses seumur hidup ke semua materi pembelajaran, dengan benefit bertanya langsung kepada mentor jika mengalami kendala dalam belajar. Dengan begitu, Anda bisa lebih produktif dan yakin dalam menyelesaikan proyek-proyek Anda dengan hasil yang lebih menarik dan profesional.

Jadi, tunggu apa lagi? Segera bergabung di BuildWithAngga dan mulailah belajar Laravel untuk membangun aplikasi yang mengesankan!