Contoh Implementasi Policy dan Gate di Laravel 12: Studi Kasus CMS Multi-Role
Artikel ini melanjutkan penjelasan konsep Policy dan Gate di Laravel 12 dengan studi kasus implementasi lengkap: sistem manajemen konten dengan beberapa level akses.
Studi Kasus: Sistem CMS dengan Multi-Role
Skenario: aplikasi CMS dengan role admin, editor, dan author. Aturannya:
- Admin bisa lakukan semua aksi di artikel mana saja
- Editor bisa buat, edit, dan publish artikel mana saja
- Author hanya bisa buat dan edit artikel miliknya sendiri
Setup Model User dengan Role
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
protected $fillable = ['name', 'email', 'password', 'role'];
public function isAdmin(): bool
{
return $this->role === 'admin';
}
public function isEditor(): bool
{
return in_array($this->role, ['admin', 'editor']);
}
}
ArticlePolicy Lengkap
<?php
namespace App\Policies;
use App\Models\Article;
use App\Models\User;
class ArticlePolicy
{
// Ini dijalankan sebelum semua method lain
// Return true = admin bypass semua check
public function before(User $user, string $ability): ?bool
{
if ($user->isAdmin()) {
return true;
}
return null; // null = lanjut ke check berikutnya
}
public function viewAny(?User $user): bool
{
// Semua orang bisa lihat daftar artikel yang published
return true;
}
public function view(?User $user, Article $article): bool
{
if ($article->status === 'published') {
return true;
}
// Draft hanya bisa dilihat pemilik atau editor
return $user && ($article->user_id === $user->id || $user->isEditor());
}
public function create(User $user): bool
{
return $user->hasVerifiedEmail();
}
public function update(User $user, Article $article): bool
{
// Editor bisa edit semua, author hanya punya sendiri
return $user->isEditor() || $article->user_id === $user->id;
}
public function delete(User $user, Article $article): bool
{
// Hanya admin (via before()) atau pemilik artikel
return $article->user_id === $user->id;
}
public function publish(User $user, Article $article): bool
{
// Hanya editor ke atas yang bisa publish
return $user->isEditor();
}
public function restore(User $user, Article $article): bool
{
return $user->isEditor() || $article->user_id === $user->id;
}
}
Menggunakan Policy di Controller
<?php
namespace App\Http\Controllers;
use App\Models\Article;
use App\Http\Requests\StoreArticleRequest;
class ArticleController extends Controller
{
public function index()
{
$this->authorize('viewAny', Article::class);
$articles = Article::with('author')
->when(!auth()->user()?->isEditor(), fn ($q) =>
$q->where('status', 'published')
->orWhere('user_id', auth()->id())
)
->paginate(15);
return view('articles.index', compact('articles'));
}
public function edit(Article $article)
{
$this->authorize('update', $article);
return view('articles.edit', compact('article'));
}
public function destroy(Article $article)
{
$this->authorize('delete', $article);
$article->delete();
return redirect()->route('articles.index')
->with('success', 'Artikel dihapus.');
}
public function publish(Article $article)
{
$this->authorize('publish', $article);
$article->update(['status' => 'published', 'published_at' => now()]);
return back()->with('success', 'Artikel dipublish.');
}
}
Policy di Blade Template
@foreach ($articles as $article)
<div>
<h2>{{ $article->title }}</h2>
@can('update', $article)
<a href="{{ route('articles.edit', $article) }}">Edit</a>
@endcan
@can('publish', $article)
@if($article->status === 'draft')
<form action="{{ route('articles.publish', $article) }}" method="POST">
@csrf @method('PATCH')
<button>Publish</button>
</form>
@endif
@endcan
@can('delete', $article)
<form action="{{ route('articles.destroy', $article) }}" method="POST">
@csrf @method('DELETE')
<button>Hapus</button>
</form>
@endcan
</div>
@endforeach
Gate untuk Aksi Global
Untuk akses fitur yang tidak terkait model tertentu, pakai Gate:
// Di AppServiceProvider
Gate::define('access-analytics', fn (User $user) => $user->isEditor());
Gate::define('export-all-data', fn (User $user) => $user->isAdmin());
// Di controller
Gate::authorize('access-analytics');
return view('analytics.dashboard');
// Di Blade
@can('access-analytics')
<a href="/analytics">Analytics</a>
@endcan
Baca Juga
Butuh tim yang bantu implementasi sistem otorisasi yang tepat untuk aplikasi Laravel Anda? Lihat layanan pengembangan aplikasi kami.
Artikel Lainnya di Kategori Laravel
10 November 2025
Contoh Penggunaan Contract di Laravel 12: Implementasi dan Binding
Kalau Anda sudah membaca artikel tentang apa itu Contract di Laravel 12, artikel ini melanjutkannya dengan contoh penggunaan nyata: bagaimana membuat implementasi Contract sendiri dan kapan ini berguna dalam proyek. Menggunakan Contract Bawaan Laravel Contract bawaan Laravel ada di namespace Illuminate\Contracts\*. Contoh yang paling sering dipakai adalah type-hinting di constructor untuk decoupling: <?php namespace App\Services; […]
Baca Artikel9 November 2025
Tutorial PostgreSQL di Laravel: Setup, JSONB, dan Full-Text Search
Laravel secara default menggunakan MySQL. Tapi kalau proyek Anda butuh fitur seperti JSON columns yang lebih canggih, full-text search bawaan, atau JSONB, PostgreSQL adalah pilihan yang solid. Artikel ini membahas cara setup PostgreSQL di Laravel, termasuk konfigurasi, perbedaan dengan MySQL, dan fitur-fitur PostgreSQL yang bisa dimanfaatkan langsung dari Eloquent. Instalasi dan Konfigurasi Pastikan extension PHP […]
Baca Artikel
Laravel 9 November 2025
Membuat Controller di Laravel 12: Resource, API, dan Best Practice
Controller adalah salah satu komponen paling sering ditulis di Laravel. Hampir setiap fitur butuh controller: dari menampilkan halaman, menyimpan data form, sampai mengembalikan JSON untuk API. Artikel ini membahas cara membuat controller di Laravel 12: dari controller dasar, resource controller, sampai best practice yang dipakai tim profesional. Membuat Controller Baru Gunakan perintah Artisan: php artisan […]
Baca ArtikelIngin Membaca Artikel Lainnya?
Temukan lebih banyak insight dan tips tentang teknologi dan bisnis digital.
Lihat Semua Artikel