Panduan mudah membuat hak akses multi-user (Admin & User) di Laravel 13 menggunakan Gate dan Policy. Dijamin rapi, aman, dan mudah dipahami!
Setelah berhasil membuat fitur autentikasi (login/register), tantangan berikutnya dalam membangun aplikasi nyata adalah mengelola Otorisasi (Authorization).
Tidak semua pengguna yang sudah masuk ke sistem boleh melakukan aksi yang sama. Pengguna biasa (User) umumnya hanya bisa melihat data mereka sendiri, sementara pengelola (Admin) memiliki hak penuh untuk mengubah atau menghapus data siapapun.
Di Laravel 13, pengelolaan hak akses ditangani secara rapi dan modular menggunakan dua fitur utama: Gate dan Policy.
Memahami Perbedaan Gate dan Policy
Sebelum masuk ke teknis penulisan kode, pahami perbedaan mendasar keduanya:
Gate: Cocok untuk memeriksa izin akses yang bersifat global atau tidak terikat pada model tertentu (misal: memeriksa apakah user memiliki role
admin).Policy: Cocok untuk mengorganisir logika izin akses yang berpusat pada Resource / Model spesifik (misal: memeriksa apakah seorang user boleh mengubah data
Postmilik orang lain).
┌─────────────────────────────────────────────────────────────────────────┐
│ STRUKTUR HAK AKSES DI LARAVEL │
├────────────────────────────────┬────────────────────────────────────────┤
│ Gate (Aturan Global / Role) │ Policy (Aturan berbasis Model Data) │
├────────────────────────────────┼────────────────────────────────────────┤
│ • `Gate::allows('admin-only')` │ • `UserPolicy::update(User $user)` │
│ • Pengecekan role umum │ • CRUD izin pada resource spesifik │
└────────────────────────────────┴────────────────────────────────────────┘
1. Persiapan: Tambahkan Kolom role pada Tabel Users
Buka file migration tabel users atau buat migration baru untuk menambahkan kolom role:
Bash
php artisan make:migration add_role_to_users_table
Isi migration dengan definisi kolom enum/string:
PHP
// database/migrations/xxxx_add_role_to_users_table.php
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->string('role')->default('user')->after('email'); // 'admin' atau 'user'
});
}
Jalankan migrasi di terminal:
Bash
php artisan migrate
Buka model app/Models/User.php dan pastikan kolom role masuk ke dalam properti $fillable:
PHP
protected $fillable = [
'name',
'email',
'password',
'role',
];
2. Mendefinisikan Gate (Aturan Global)
Buka file app/Providers/AppServiceProvider.php dan daftarkan aturan Gate di dalam method boot():
PHP
namespace App\Providers;
use App\Models\User;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot(): void
{
// Mendefinisikan Gate khusus Admin
Gate::define('admin-only', function (User $user) {
return $user->role === 'admin';
});
}
}
Cara Memakai Gate di Controller & Blade View:
Di Controller:
PHP
if (Gate::denies('admin-only')) { abort(403, 'Akses Ditolak! Anda Bukan Admin.'); }Di File Blade View:
HTML
@can('admin-only') <a href="/admin/dashboard" class="btn btn-primary">Menu Rahasia Admin</a> @endcan
3. Membuat Policy (Aturan berbasis Model)
Misalkan kita punya model Article. Kita ingin mengatur bahwa artikel hanya boleh diubah atau dihapus oleh pemiliknya sendiri, kecuali jika yang login adalah Admin.
Jalankan perintah Artisan untuk membuat Policy yang terhubung langsung dengan model Article:
Bash
php artisan make:policy ArticlePolicy --model=Article
Buka file app/Policies/ArticlePolicy.php dan sesuaikan method update serta delete:
PHP
namespace App\Policies;
use App\Models\Article;
use App\Models\User;
class ArticlePolicy
{
/**
* Menentukan apakah user boleh memperbarui artikel ini.
*/
public function update(User $user, Article $article): bool
{
// Admin selalu boleh edit, atau user pemilik artikel tersebut
return $user->role === 'admin' || $user->id === $article->user_id;
}
/**
* Menentukan apakah user boleh menghapus artikel ini.
*/
public function delete(User $user, Article $article): bool
{
return $user->role === 'admin' || $user->id === $article->user_id;
}
}
4. Menerapkan Policy di Controller
Buka ArticleController.php dan manfaatkan method $this->authorize() atau Gate::authorize():
PHP
namespace App\Http\Controllers;
use App\Models\Article;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
class ArticleController extends Controller
{
public function edit(Article $article)
{
// Memeriksa aturan 'update' yang ada di ArticlePolicy
Gate::authorize('update', $article);
return view('articles.edit', compact('article'));
}
public function destroy(Article $article)
{
// Memeriksa aturan 'delete' yang ada di ArticlePolicy
Gate::authorize('delete', $article);
$article->delete();
return redirect()->route('articles.index')->with('success', 'Artikel berhasil dihapus');
}
}
Jika pengguna yang tidak berhak mencoba mengakses route tersebut, Laravel 13 akan secara otomatis menghentikan proses dan menampilkan halaman 403 Forbidden.
Kesimpulan
Dengan memisahkan logika hak akses ke dalam Gate dan Policy, struktur kode di Laravel 13 milikmu menjadi jauh lebih bersih (clean code), tidak menumpuk di controller, serta terhindar dari kebocoran keamanan akses data.
Ditulis oleh
Egi Samsul Mu'arif
Web & Mobile Developer



