Để phân quyền CRUD cho các trang (pages) trong Laravel sử dụng package spatie/laravel-permission

✅ Bước 1: Cài đặt package

bashCopyEditcomposer require spatie/laravel-permission

Đăng service provider và publish file config/migrations:

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

✅ Bước 2: Cấu hình model User

Thêm HasRoles vào model User:

phpCopyEdituse Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    use HasRoles;
}

✅ Bước 3: Tạo Roles và Permissions

Bạn có thể chạy trong seeder, controller hoặc tinker:

Tạo Seeder

php artisan make:seeder RolePermissionSeeder

✍ Nội dung database/seeders/RolePermissionSeeder.php:

<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
class RolePermissionSeeder extends Seeder
{
    public function run(): void
    {
        // Danh sách quyền CRUD cho page
        $permissions = [
            'view page',
            'create page',
            'edit page',
            'delete page',
        ];
        // Tạo quyền nếu chưa tồn tại
        foreach ($permissions as $permission) {
            Permission::firstOrCreate(['name' => $permission]);
        }
        // Tạo role admin và gán toàn bộ quyền
        $admin = Role::firstOrCreate(['name' => 'admin']);
        $admin->syncPermissions(Permission::all());

        // Tạo role editor chỉ được xem và chỉnh sửa
        $editor = Role::firstOrCreate(['name' => 'editor']);
        $editor->syncPermissions(['view page', 'edit page']);
        // Gán role admin cho user đầu tiên
        $user = \App\Models\User::first();
        if ($user) {
            $user->assignRole('admin');
        }
    }
}

✅ Chạy Seeder:

php artisan db:seed --class=RolePermissionSeeder

✅ 2. Policy cho Page

📄 Tạo Policy

php artisan make:policy PagePolicy --model=Page

app\Policies\PagePolicy.php

<?php
namespace App\Policies;
use App\Models\Page;
use App\Models\User;
use Illuminate\Auth\Access\Response;
class PagePolicy
{
  /**
   * Determine whether the user can view any models.
   */
  public function viewAny(User $user): bool
  {
    return false;
  }
  /**
   * Determine whether the user can view the model.
   */
  public function view(User $user, Page $page): bool
  {
    return $user->can('view page');
  }
  /**
   * Determine whether the user can create models.
   */
  public function create(User $user): bool
  {
    return $user->can('create page');
  }
  /**
   * Determine whether the user can update the model.
   */
  public function update(User $user, Page $page): bool
  {
    return $user->can('edit page');
  }
  /**
   * Determine whether the user can delete the model.
   */
  public function delete(User $user, Page $page): bool
  {
    return $user->can('delete page');
  }
  /**
   * Determine whether the user can restore the model.
   */
  public function restore(User $user, Page $page): bool
  {
    return false;
  }
  /**
   * Determine whether the user can permanently delete the model.
   */
  public function forceDelete(User $user, Page $page): bool
  {
    return false;
  }
}

✅ 3. Đăng ký Policy trong AuthServiceProvider

app\Providers\AppServiceProvider.php

<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Models\Page;
use App\Policies\PagePolicy;
class AppServiceProvider extends ServiceProvider
{
  protected $policies = [
    Page::class => PagePolicy::class,
  ];
  /**
   * Register any application services.
   */
  public function register(): void
  {
    //
  }
  /**
   * Bootstrap any application services.
   */
  public function boot(): void
  {
    //
  }
}

✅ 4. Sử dụng Policy trong Controller hoặc Blade

Trong Controller:

$this->authorize('update', $page);

Trong Blade:

@can('create page')
    <a href="{{ route('pages.create') }}">Tạo trang</a>
@endcan

@can('edit page')
    <a href="{{ route('pages.edit', $page) }}">Chỉnh sửa</a>
@endcan

✅ Bước 4: Middleware kiểm tra quyền

Bạn có thể dùng middleware permission do Spatie cung cấp.

Đăng ký middleware trong app/Http/Kernel.php nếu chưa có:

'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,

Trong Laravel 11 và các phiên bản mới hơn, các middleware, bao gồm cả middleware của Spatie, sẽ được đăng ký trong file bootstrap/app.php.

bootstrap\app.php

<?php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Spatie\Permission\Middleware\PermissionMiddleware;
use Spatie\Permission\Middleware\RoleMiddleware;
return Application::configure(basePath: dirname(__DIR__))
  ->withRouting(
    web: __DIR__ . '/../routes/web.php',
    commands: __DIR__ . '/../routes/console.php',
    health: '/up',
  )
  ->withMiddleware(function (Middleware $middleware) {
    // Đăng ký middleware của Spatie tại đây
    $middleware->alias([
      'permission' => PermissionMiddleware::class,
      'role' => RoleMiddleware::class,
    ]);
    // Bạn cũng có thể thêm các middleware vào nhóm web hoặc api nếu cần
    // $middleware->web(append: [
    //     \App\Http\Middleware\TrustProxies::class,
    // ]);
    // $middleware->api(prepend: [
    //     \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
    // ]);
  })
  ->withExceptions(function (Exceptions $exceptions) {
    //
  })->create();

Sau khi bạn đã đăng ký như trên, bạn có thể sử dụng các middleware này trong các route của mình như bình thường:

// routes/web.php
use Illuminate\Support\Facades\Route;
Route::get('/admin/posts', function () {
    // Chỉ những người dùng có quyền 'manage posts' mới có thể truy cập
})->middleware(['permission:manage posts']);

Route::get('/admin/users', function () {
    // Chỉ những người dùng có vai trò 'admin' mới có thể truy cập
})->middleware(['role:admin']);

Áp dụng trong route:

Route::group(['middleware' => ['auth']], function () {
    Route::get('/pages', [PageController::class, 'index'])->middleware('permission:view page');
    Route::get('/pages/create', [PageController::class, 'create'])->middleware('permission:create page');
    Route::post('/pages', [PageController::class, 'store'])->middleware('permission:create page');
    Route::get('/pages/{page}/edit', [PageController::class, 'edit'])->middleware('permission:edit page');
    Route::put('/pages/{page}', [PageController::class, 'update'])->middleware('permission:edit page');
    Route::delete('/pages/{page}', [PageController::class, 'destroy'])->middleware('permission:delete page');
});

✅ Bước 5: Hiển thị UI theo quyền (optional)

Trong Blade:

@can('create page')
    <a href="{{ route('pages.create') }}">Tạo mới trang</a>
@endcan

Last updated

Was this helpful?