Middleware auth di episode sebelumnya cuma cek "sudah login atau belum" — semua user yang login dianggap setara. Untuk blog sungguhan, biasanya cuma admin yang boleh kelola konten. Episode ini kita bikin role sederhana tanpa package tambahan seperti Spatie Permission — cukup satu kolom boolean dan satu middleware custom.
User yang login tapi bukan admin mendapat 403 Forbidden saat akses /posts/create.
Migration: tambah kolom is_admin
php artisan make:migration add_is_admin_to_users_table --table=users
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->boolean('is_admin')->default(false)->after('password');
});
}
Update model User
#[Fillable(['name', 'email', 'password', 'is_admin'])]
class User extends Authenticatable
{
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
'is_admin' => 'boolean',
];
}
}
'is_admin' => 'boolean' di casts memastikan nilai dari database (0/1) otomatis dikonversi jadi true/false di PHP, bukan integer mentah.
Membuat custom middleware
php artisan make:middleware EnsureUserIsAdmin
class EnsureUserIsAdmin
{
public function handle(Request $request, Closure $next): Response
{
if (! $request->user()?->is_admin) {
abort(403, 'Only admins can manage posts.');
}
return $next($request);
}
}
Middleware ini menolak request dengan HTTP 403 (Forbidden) kalau user yang login bukan admin.
Mendaftarkan alias middleware
Laravel 11+ (termasuk 13) mendaftarkan middleware lewat bootstrap/app.php, bukan Kernel.php seperti versi lama:
->withMiddleware(function (Middleware $middleware): void {
$middleware->alias([
'admin' => \App\Http\Middleware\EnsureUserIsAdmin::class,
]);
})
Menggabungkan dengan middleware auth
Route::middleware(['auth', 'admin'])->group(function () {
Route::resource('posts', PostController::class)->except(['index', 'show']);
});
Dua middleware ini dijalankan berurutan: auth dulu (pastikan sudah login), baru admin (pastikan yang login itu admin). Kalau salah satu gagal, request langsung ditolak sebelum sampai ke controller.
Update seeder
User::factory()->create([
'name' => 'Test User',
'email' => 'test@example.com',
'is_admin' => true,
]);
Menyembunyikan UI dari non-admin
@auth
@if (Auth::user()->is_admin)
<a class="nav-link" href="{{ route('posts.create') }}">New Post</a>
@endif
@endauth
Testing: admin lolos, user biasa ditolak
# Login sebagai admin, lalu:
curl -b admin-cookies.txt -o /dev/null -w "%{http_code}\n" http://laravel13-blog-dasar.test/posts/create
# -> 200
# Login sebagai user biasa (is_admin: false), lalu:
curl -b user-cookies.txt -o /dev/null -w "%{http_code}\n" http://laravel13-blog-dasar.test/posts/create
# -> 403
Kenapa tidak pakai package permission dari awal?
Untuk kasus sederhana — satu level admin vs user biasa — package seperti Spatie Permission adalah overkill. Kolom boolean + middleware custom sudah cukup, jauh lebih mudah dipahami untuk pemula, dan bisa di-upgrade ke sistem role/permission yang lebih kompleks nanti kalau memang dibutuhkan.
Selanjutnya
Aplikasi sudah fungsional penuh secara lokal. Episode berikutnya kita bahas cara deploy ke VPS sungguhan supaya bisa diakses publik.