Laravel
Auth & Roles
Authentication setup with Breeze & Sanctum, role-based access control using Gates and Policies, middleware guards, and manual auth checks in controllers and Blade views.
1. Installation & Setup: Install
spatie/laravel-permission. Publish migrations, jalankan migrate, dan WAJIB menambahkan trait HasRoles ke model User.
terminal & User.php
BASH/PHP
# 1. Install package
composer require spatie/laravel-permission
# 2. Publish config & migration
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
# 3. Clear cache & Migrate
php artisan optimize:clear
php artisan migrate
# 4. Tambahkan Trait 'HasRoles' di model User
// app/Models/User.php
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasRoles; // <-- WAJIB TAMBAHKAN INI
// ...
}
2. Create Roles & Permissions: Gunakan model
Role dan Permission dari Spatie untuk membuat role baru dan memberikan hak akses (permission). Biasanya ini ditaruh di DatabaseSeeder.
Seeder / Controller
PHP
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
// Membuat Permission
Permission::create(['name' => 'edit articles']);
Permission::create(['name' => 'delete articles']);
Permission::create(['name' => 'publish articles']);
Permission::create(['name' => 'unpublish articles']);
// Membuat Role
$writerRole = Role::create(['name' => 'writer']);
$adminRole = Role::create(['name' => 'admin']);
// Memberikan permission ke role
$writerRole->givePermissionTo('edit articles');
$writerRole->givePermissionTo('publish articles');
// Bisa juga pakai array
$adminRole->givePermissionTo([
'edit articles',
'delete articles',
'publish articles',
'unpublish articles'
]);
// Atau pakai syncPermissions (akan menghapus yang tidak ada di list)
$writerRole->syncPermissions(['edit articles']);
3. Assign Roles ke User: Menggunakan instance model User (yang sudah dipasang Trait
HasRoles), Anda bisa memberikan role, mencabut, atau mengeceknya.
Controller
PHP
$user = User::find(1);
// Memberikan role ke user
$user->assignRole('writer');
$user->assignRole(['writer', 'admin']); // multiple
// Menghapus role dari user
$user->removeRole('writer');
// Sinkronisasi role (menghapus yang lama, set yang baru)
$user->syncRoles(['super-admin']);
// Cek apakah user punya role tertentu (mengembalikan boolean)
$user->hasRole('writer');
$user->hasAnyRole(['writer', 'admin']);
$user->hasAllRoles(['writer', 'admin']);
// Cek permission langsung ke user (meskipun permission ada di role nya, akan return true)
$user->hasPermissionTo('edit articles');
$user->hasAnyPermission(['edit articles', 'delete articles']);
// Memberikan direct permission ke user (bypass role)
$user->givePermissionTo('edit articles');
4. Route Middleware: Spatie menyediakan middleware
role, permission, dan role_or_permission untuk melindungi route. (Pastikan mendaftarkan array alias di bootstrap/app.php jika Laravel 11 membutuhkan alias).
routes/web.php
PHP
// Di Laravel 11, Anda bisa langsung pakai middleware string dari spatie
// Atur di routes/web.php
// 1. Cek berdasarkan Role
Route::group(['middleware' => ['role:super-admin']], function () {
Route::get('/settings', [SettingController::class, 'index']);
});
// 2. Cek multiple Role (pakai pipe | )
Route::group(['middleware' => ['role:super-admin|admin']], function () {
Route::get('/admin-panel', [AdminController::class, 'index']);
});
// 3. Cek berdasarkan Permission
Route::group(['middleware' => ['permission:publish articles']], function () {
Route::get('/publish', [ArticleController::class, 'publish']);
});
// 4. Role atau Permission
Route::group(['middleware' => ['role_or_permission:super-admin|edit articles']], function () {
Route::get('/edit', [ArticleController::class, 'edit']);
});
5. Blade Directives: Spatie menambahkan directives khusus seperti
@role atau @hasanyrole untuk mengatur UI mana yang tampil berdasarkan role.
resources/views/...
BLADE
{{-- Cek Role --}}
@role('writer')
I am a writer!
@else
I am not a writer...
@endrole
{{-- Cek Multiple Roles --}}
@hasrole('writer|admin')
I am either a writer or an admin!
@endhasrole
@hasanyrole($collectionOfRoles)
I have one or more of these roles!
@endhasanyrole
@hasallroles('writer|admin')
I am both a writer and an admin!
@endhasallroles
{{-- Cek Permission (Bisa pakai @can bawaan Laravel atau dari Spatie) --}}
@can('edit articles')
<button>Edit Article</button>
@endcan
{{-- Cek kombinasi --}}
@unlessrole('does not have this role')
I do not have the role
@endunlessrole
6. Controller Checks: Jika Anda butuh logika custom di Controller, gunakan
hasRole() atau hasPermissionTo().
app/Http/Controllers/ArticleController.php
PHP
class ArticleController extends Controller
{
public function update(Request $request, Article $article)
{
// 1. Menggunakan method can() bawaan user
if ($request->user()->cannot('edit articles')) {
abort(403);
}
// 2. Menggunakan method khusus Spatie
if (! auth()->user()->hasRole('admin')) {
abort(403, 'Unauthorized action.');
}
// 3. Melempar exception otomatis dari Spatie
// Jika tidak punya permission, akan melempar Spatie\Permission\Exceptions\UnauthorizedException
if (! auth()->user()->hasPermissionTo('edit articles')) {
throw UnauthorizedException::forPermissions(['edit articles']);
}
// ...
}
}
7. Super Admin Bypass: Daftarkan
Gate::before di ServiceProvider agar role 'Super Admin' tidak perlu dicek lagi tiap permissionnya (otomatis allow semua).
app/Providers/AppServiceProvider.php
PHP
// app/Providers/AppServiceProvider.php
use Illuminate\Support\Facades\Gate;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
// Secara implisit mengabulkan (grant) semua permission kepada role Super Admin
// Jadi tidak perlu mendaftarkan permission satu-satu untuk role ini.
Gate::before(function ($user, $ability) {
return $user->hasRole('Super Admin') ? true : null;
});
}
}