Spatie Laravel Permission không chỉ mạnh mẽ trong việc quản lý vai trò (roles) và quyền (permissions) cơ bản, mà còn cung cấp nhiều tính năng nâng cao để giúp bạn tùy chỉnh ứng dụng Laravel của mình theo cách tối ưu và linh hoạt nhất. Dưới đây là bài viết hướng dẫn chi tiết về các tính năng nâng cao của Spatie Laravel Permission.

1. Multi-Tenancy

Spatie Laravel Permission hỗ trợ quản lý vai trò và quyền theo từng tenant (tổ chức hoặc nhóm người dùng). Điều này rất hữu ích khi bạn phát triển ứng dụng SaaS với nhiều tổ chức khác nhau.

Cách cấu hình

  • Kích hoạt multi-tenancy trong file cấu hình config/permission.php:
php
'cache' => [
    'key' => 'spatie.permission.cache',
    'store' => 'default',
    'tenant_key' => 'tenant_id', // Tên cột nhận diện tenant
],
  • Sử dụng middleware để áp dụng quyền theo tenant:
php
use Illuminate\Support\Facades\Auth;

$tenantId = Auth::user()->tenant_id;
app(\Spatie\Permission\PermissionRegistrar::class)->setPermissionsTeamId($tenantId);

2. Gán quyền trực tiếp cho người dùng

Thay vì gán quyền thông qua vai trò, bạn có thể gán trực tiếp quyền cụ thể cho từng người dùng.

Cách thực hiện

  • Gán quyền trực tiếp:
php
$user = User::find(1);
$user->givePermissionTo('edit articles');
  • Kiểm tra quyền trực tiếp:
php
if ($user->hasPermissionTo('edit articles')) {
    // Người dùng có quyền chỉnh sửa bài viết
}

3. Scope truy vấn theo role/permission

Bạn có thể sử dụng scope truy vấn để lấy danh sách người dùng, role, hoặc permission liên quan.

Ví dụ

  • Lấy danh sách người dùng có một role cụ thể:
php
$usersWithRole = User::role('admin')->get();
  • Lấy danh sách người dùng có một permission cụ thể:
php
$usersWithPermission = User::permission('edit articles')->get();

4. Kiểm tra nhiều quyền cùng lúc

Spatie Laravel Permission cho phép kiểm tra nhiều quyền đồng thời với các điều kiện linh hoạt.

Ví dụ

  • Kiểm tra nếu người dùng có ít nhất một trong các quyền:
php
if ($user->hasAnyPermission(['edit articles', 'delete articles'])) {
    // Người dùng có một trong hai quyền
}
  • Kiểm tra nếu người dùng có tất cả các quyền:
php
if ($user->hasAllPermissions(['edit articles', 'delete articles'])) {
    // Người dùng có cả hai quyền
}

5. Kế thừa role (Role Hierarchy)

Bạn có thể tạo hệ thống vai trò phân cấp, trong đó vai trò cao cấp tự động kế thừa các quyền của vai trò thấp hơn.

Cách thực hiện

Dùng logic thủ công để kiểm tra vai trò cấp bậc:

php
function hasHigherRole(User $user, $role) {
    $roleHierarchy = [
        'super-admin' => 3,
        'admin' => 2,
        'editor' => 1,
    ];

    return $roleHierarchy[$user->roles->first()->name] >= $roleHierarchy[$role];
}

6. Quản lý permisson cho nhiều Model

Spatie Laravel Permission cho phép sử dụng quyền với nhiều loại model khác nhau.

Cách thực hiện

  • Định nghĩa permission cho một model cụ thể:
php
use Spatie\Permission\Models\Permission;

$permission = Permission::create([
    'name' => 'edit articles',
    'guard_name' => 'web',
    'model_type' => 'App\Models\Article',
]);
  • Gán permission theo từng model:
php
$article = Article::find(1);
$user->givePermissionTo('edit', $article);
  • Kiểm tra permission trên model:
php
if ($user->can('edit', $article)) {
    // Người dùng có quyền chỉnh sửa bài viết cụ thể này
}

7. Tích hợp bộ nhớ đệm (Caching)

Package hỗ trợ caching để tăng tốc truy vấn quyền, đặc biệt quan trọng đối với các ứng dụng lớn.

Cấu hình

  • Kích hoạt caching trong config/permission.php:
php
'cache' => [
    'expiration_time' => 3600, // Thời gian lưu cache (giây)
],
  • Xóa cache khi cần thiết:
shell
php artisan permission:cache-reset

Hoặc trong code:

php
app(\Spatie\Permission\PermissionRegistrar::class)->forgetCachedPermissions();

8. Xử lý sự kiện (Events) khi thay đổi role/permission

Bạn có thể lắng nghe các sự kiện khi vai trò hoặc quyền được thay đổi.

Ví dụ

  • Đăng ký sự kiện trong EventServiceProvider:
php
use Spatie\Permission\Events\PermissionAssigned;
use Spatie\Permission\Events\RoleAssigned;

protected $listen = [
    PermissionAssigned::class => [
        \App\Listeners\LogPermissionAssigned::class,
    ],
    RoleAssigned::class => [
        \App\Listeners\LogRoleAssigned::class,
    ],
];
  • Tạo listener:
php
namespace App\Listeners;

use Spatie\Permission\Events\PermissionAssigned;

class LogPermissionAssigned
{
    public function handle(PermissionAssigned $event)
    {
        \Log::info("Permission '{$event->permission->name}' assigned to {$event->model->name}");
    }
}

9. Tùy chỉnh Guard name

Nếu bạn sử dụng nhiều guard (như web, api), bạn có thể tùy chỉnh cách Spatie Laravel Permission hoạt động với từng guard.

Thực hiện

  • Chỉ định guard khi tạo role hoặc permission:
php
Role::create(['name' => 'admin', 'guard_name' => 'api']);
Permission::create(['name' => 'edit articles', 'guard_name' => 'api']);
  • Gán guard mặc định trong config/permission.php:
php
'guards' => ['web', 'api'],

10. Tích hợp với Middleware tùy chỉnh

Ngoài các middleware mặc định, bạn có thể tạo middleware tùy chỉnh để kiểm soát truy cập chi tiết hơn.

Ví dụ

  • Tạo middleware:
php
namespace App\Http\Middleware;

use Closure;

class CheckCustomPermission
{
    public function handle($request, Closure $next, $permission)
    {
        if (!auth()->user()->can($permission)) {
            abort(403, 'Unauthorized');
        }

        return $next($request);
    }
}
  • Sử dụng trong route:
php
Route::middleware(['check.custom.permission:edit articles'])->group(function () {
    Route::get('/edit-article', [ArticleController::class, 'edit']);
});

Kết luận

Spatie Laravel Permission không chỉ giới hạn ở việc quản lý vai trò và quyền cơ bản, mà còn mang đến nhiều tính năng nâng cao để hỗ trợ xây dựng các ứng dụng phức tạp. Từ hỗ trợ multi-tenancy, caching, đến sự kiện và scope truy vấn, bạn có thể tùy chỉnh mọi thứ để đáp ứng nhu cầu của mình.

Hãy khám phá và áp dụng những tính năng này để tối ưu hóa ứng dụng Laravel của bạn! 🚀

Nếu có bất kỳ câu hỏi nào, đừng ngần ngại để lại bình luận hoặc theo dõi CodeTutHub để cập nhật các bài viết lập trình mới nhất. ❤️