Tuyệt, để xây dựng giao diện quản lý người dùng và phân quyền với spatie/laravel-permission

Tuyệt, để xây dựng giao diện quản lý người dùng và phân quyền với spatie/laravel-permission, ta sẽ làm theo các bước sau:

✅ 1. Cài đặt mối quan hệ Role/Permission/User

Trong User model:

use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
    use HasRoles;
}

✅ 2. Tạo Seeder cho Roles và Permissions

bphp artisan make:seeder RolePermissionSeeder

Trong database/seeders/RolePermissionSeeder.php:

use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
public function run()
{
    $permissions = [
        'view page',
        'create page',
        'edit page',
        'delete page',
        'manage users',
        'manage roles'
    ];
    foreach ($permissions as $permission) {
        Permission::firstOrCreate(['name' => $permission]);
    }

    $admin = Role::firstOrCreate(['name' => 'admin']);
    $admin->syncPermissions($permissions);

    $editor = Role::firstOrCreate(['name' => 'editor']);
    $editor->syncPermissions(['view page', 'edit page']);

    $user = \App\Models\User::find(1); // hoặc user đầu tiên
    if ($user) $user->assignRole('admin');
}

✅ 3. Tạo Controller quản lý User/Role/Permission

php artisan make:controller Admin/UserController --resource
php artisan make:controller Admin/RoleController --resource

✅ 4. Route

Trong routes/web.php hoặc routes/admin.php:

routes\web.php

<?php
use App\Http\Controllers\Admin\PageController;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
use UniSharp\LaravelFilemanager\Lfm;
Auth::routes();
Route::get('/', function () {
  return view('welcome');
});
// Route::prefix('admin')->name('admin.')->middleware(['auth'])->group(function () {
//   Route::resource('pages', PageController::class);
// });
Route::middleware(['auth', 'permission:view page'])->prefix('admin')->name('admin.')->group(function () {
  Route::resource('pages', PageController::class);
});
// LaravelFilemanager
Route::group(['prefix' => 'laravel-filemanager', 'middleware' => ['web', 'auth']], function () {
  Lfm::routes();
});
require __DIR__.'/admin.php';

routes\admin.php

<?php
use App\Http\Controllers\Admin\RoleController;
use App\Http\Controllers\Admin\UserController;
use Illuminate\Routing\Route;
Route::middleware(['auth'])->prefix('admin')->name('admin.')->group(function () {
  Route::resource('users', UserController::class)->middleware('permission:manage users');
  Route::resource('roles', RoleController::class)->middleware('permission:manage roles');
});

✅ 5. Giao diện phân quyền (UserController)

Trong UserController:

use Spatie\Permission\Models\Role;
public function edit(User $user)
{
    $roles = Role::all();
    return view('admin.users.edit', compact('user', 'roles'));
}
public function update(Request $request, User $user)
{
    $request->validate([
        'roles' => 'array',
    ]);
    $user->syncRoles($request->roles);
    return redirect()->route('admin.users.index')->with('success', 'Cập nhật vai trò thành công.');
}

resources\views\admin\users\index.blade.php

@extends('layouts.admin')
@section('content')
<div class="container mt-4">
  <h2>Quản lý người dùng</h2>
  <table class="table">
    <thead>
      <tr>
        <th>Email</th>
        <th>Vai trò</th>
        <th>Thao tác</th>
      </tr>
    </thead>
    <tbody>
      @foreach($users as $user)
      <tr>
        <td>{{ $user->email }}</td>
        <td>{{ $user->getRoleNames()->join(', ') }}</td>
        <td>
          <a href="{{ route('admin.users.edit', $user) }}" class="btn btn-sm btn-primary">Phân quyền</a>
        </td>
      </tr>
      @endforeach
    </tbody>
  </table>
</div>
@endsection

resources\views\admin\users\edit.blade.php

@extends('layouts.admin')
@section('content')
<div class="container mt-4">
  <h2>Phân quyền cho: {{ $user->email }}</h2>
  <form method="POST" action="{{ route('admin.users.update', $user) }}">
    @csrf
    @method('PUT')
    <div class="mb-3">
      <label class="form-label">Vai trò</label>
      @foreach($roles as $role)
        <div class="form-check">
          <input class="form-check-input" type="checkbox" name="roles[]" value="{{ $role->name }}"
            {{ $user->hasRole($role->name) ? 'checked' : '' }}>
          <label class="form-check-label">{{ $role->name }}</label>
        </div>
      @endforeach
    </div>
    <button type="submit" class="btn btn-primary">Cập nhật</button>
    <a href="{{ route('admin.users.index') }}" class="btn btn-secondary">Quay lại</a>
  </form>
</div>
@endsection

Chúng ta sẽ bổ sung logic vào các phương thức create, store, và show.

app\Http\Controllers\Admin\UserController.php

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Spatie\Permission\Models\Role;
use Illuminate\Support\Facades\Hash; // Cần dùng để mã hóa mật khẩu
class UserController extends Controller
{
  /**
   * Display a listing of the resource.
   */
  public function index()
  {
    // $users = User::all();
    // Lấy tất cả người dùng và eager load các vai trò của họ để tránh N+1 query
    $users = User::with('roles')->get();
    return view('admin.users.index', compact('users'));
  }
  /**
   * Show the form for creating a new resource.
   */
  public function create()
  {
    // Lấy tất cả các vai trò để hiển thị trên form tạo người dùng
    $roles = Role::all();
    return view('admin.users.create', compact('roles'));
  }
  /**
   * Store a newly created resource in storage.
   */
  public function store(Request $request)
  {
    // Validate dữ liệu đầu vào
    $request->validate([
      'name' => 'required|string|max:255',
      'email' => 'required|string|email|max:255|unique:users', // Email phải là duy nhất
      'password' => 'required|string|min:8|confirmed', // Password tối thiểu 8 ký tự và phải được xác nhận
      'roles' => 'nullable|array', // Vai trò là một mảng, có thể rỗng
      'roles.*' => 'exists:roles,name', // Mỗi vai trò trong mảng phải tồn tại trong bảng roles
    ]);
    // Tạo người dùng mới
    $user = User::create([
      'name' => $request->name,
      'email' => $request->email,
      'password' => Hash::make($request->password), // Mã hóa mật khẩu
    ]);
    // Gán vai trò cho người dùng nếu có
    if ($request->has('roles')) {
      $user->syncRoles($request->roles);
    }
    return redirect()->route('admin.users.index')->with('success', 'Tạo người dùng mới thành công.');
  }
  /**
   * Display the specified resource.
   */
  public function show(User $user) // Sử dụng Route Model Binding
  {
    // Lấy thông tin chi tiết của người dùng, bao gồm cả các vai trò của họ
    $user->load('roles');
    return view('admin.users.show', compact('user'));
  }
  /**
   * Show the form for editing the specified resource.
   */
  public function edit(User $user)
  {
    $roles = Role::all();
    return view('admin.users.edit', compact('user', 'roles'));
  }
  /**
   * Update the specified resource in storage.
   */
  public function update(Request $request, User $user)
  {
    // $request->validate([
    //   'roles' => 'array',
    // ]);
    // $user->syncRoles($request->roles);
    // return redirect()->route('admin.users.index')->with('success', 'Cập nhật vai trò thành công.');
    $request->validate([
      'name' => 'required|string|max:255',
      'email' => 'required|string|email|max:255|unique:users,email,' . $user->id, // Email phải là duy nhất, bỏ qua email của chính user này
      'password' => 'nullable|string|min:8|confirmed', // Mật khẩu có thể không thay đổi, hoặc thay đổi thì cần xác nhận
      'roles' => 'array',
      'roles.*' => 'exists:roles,name',
    ]);
    $user->update([
      'name' => $request->name,
      'email' => $request->email,
    ]);
    // Cập nhật mật khẩu nếu có
    if ($request->filled('password')) {
      $user->update([
        'password' => Hash::make($request->password),
      ]);
    }
    // Đồng bộ vai trò
    $user->syncRoles($request->roles);
    return redirect()->route('admin.users.index')->with('success', 'Cập nhật người dùng thành công.');
  }
  /**
   * Remove the specified resource from storage.
   */
  public function destroy(User $user)
  {
    // Bạn có thể thêm xác nhận hoặc kiểm tra quyền trước khi xóa
    $user->delete();
    return redirect()->route('admin.users.index')->with('success', 'Xóa người dùng thành công.');
  }
}

resources\views\admin\users\create.blade.php

@extends('layouts.admin') {{-- Giả định bạn có layout admin --}}
@section('content')
<div class="container">
  <h1>Tạo người dùng mới</h1>
  @if ($errors->any())
  <div class="alert alert-danger">
    <ul>
      @foreach ($errors->all() as $error)
      <li>{{ $error }}</li>
      @endforeach
    </ul>
  </div>
  @endif
  <form action="{{ route('admin.users.store') }}" method="POST">
    @csrf
    <div class="mb-3">
      <label for="name" class="form-label">Tên người dùng:</label>
      <input type="text" class="form-control" id="name" name="name" value="{{ old('name') }}" required>
    </div>
    <div class="mb-3">
      <label for="email" class="form-label">Email:</label>
      <input type="email" class="form-control" id="email" name="email" value="{{ old('email') }}" required>
    </div>
    <div class="mb-3">
      <label for="password" class="form-label">Mật khẩu:</label>
      <input type="password" class="form-control" id="password" name="password" required>
    </div>
    <div class="mb-3">
      <label for="password_confirmation" class="form-label">Xác nhận mật khẩu:</label>
      <input type="password" class="form-control" id="password_confirmation" name="password_confirmation" required>
    </div>
    <div class="mb-3">
      <label class="form-label">Vai trò:</label>
      @foreach($roles as $role)
      <div class="form-check">
        <input class="form-check-input" type="checkbox" name="roles[]" value="{{ $role->name }}" id="role_{{ $role->id }}" {{ in_array($role->name, old('roles', [])) ? 'checked' : '' }}>
        <label class="form-check-label" for="role_{{ $role->id }}">
          {{ $role->name }}
        </label>
      </div>
      @endforeach
    </div>
    <button type="submit" class="btn btn-primary">Tạo người dùng</button>
    <a href="{{ route('admin.users.index') }}" class="btn btn-secondary">Hủy</a>
  </form>
</div>
@endsection

resources\views\admin\users\edit.blade.php

@extends('layouts.admin')
@section('content')
<div class="container mt-4">
  <h2>Phân quyền cho: {{ $user->email }}</h2>
  <form method="POST" action="{{ route('admin.users.update', $user) }}">
    @csrf
    @method('PUT')
    <div class="mb-3">
      <label class="form-label">Vai trò</label>
      @foreach($roles as $role)
        <div class="form-check">
          <input class="form-check-input" type="checkbox" name="roles[]" value="{{ $role->name }}"
            {{ $user->hasRole($role->name) ? 'checked' : '' }}>
          <label class="form-check-label">{{ $role->name }}</label>
        </div>
      @endforeach
    </div>
    <button type="submit" class="btn btn-primary">Cập nhật</button>
    <a href="{{ route('admin.users.index') }}" class="btn btn-secondary">Quay lại</a>
  </form>
</div>
@endsection

resources\views\admin\users\index.blade.php

@extends('layouts.admin')
@section('content')
<div class="container mt-4">
  <h2>Quản lý người dùng</h2>
  <table class="table">
    <thead>
      <tr>
        <th>Email</th>
        <th>Vai trò</th>
        <th>Thao tác</th>
      </tr>
    </thead>
    <tbody>
      @foreach($users as $user)
      <tr>
        <td>{{ $user->email }}</td>
        <td>{{ $user->getRoleNames()->join(', ') }}</td>
        <td>
          <a href="{{ route('admin.users.edit', $user) }}" class="btn btn-sm btn-primary">Phân quyền</a>
          <form action="{{ route('admin.users.destroy', $user) }}" method="POST" class="d-inline-block" onsubmit="return confirm('Bạn có chắc chắn muốn xóa người dùng này?');">
            @csrf
            @method('DELETE')
            <button type="submit" class="btn btn-danger">Xóa</button>
          </form>
        </td>
      </tr>
      @endforeach
    </tbody>
  </table>
</div>
@endsection

resources\views\admin\users\show.blade.php

@extends('layouts.admin') {{-- Giả định bạn có layout admin --}}
@section('content')
<div class="container">
  <h1>Chi tiết người dùng: {{ $user->name }}</h1>
  <div class="card">
    <div class="card-body">
      <h5 class="card-title">ID: {{ $user->id }}</h5>
      <p class="card-text"><strong>Tên:</strong> {{ $user->name }}</p>
      <p class="card-text"><strong>Email:</strong> {{ $user->email }}</p>
      <p class="card-text"><strong>Ngày tạo:</strong> {{ $user->created_at->format('d/m/Y H:i') }}</p>
      <p class="card-text"><strong>Ngày cập nhật:</strong> {{ $user->updated_at->format('d/m/Y H:i') }}</p>
      <p class="card-text"><strong>Vai trò:</strong>
        @forelse ($user->roles as $role)
        <span class="badge bg-primary">{{ $role->name }}</span>
        @empty
        Không có vai trò nào.
        @endforelse
      </p>
      <a href="{{ route('admin.users.edit', $user) }}" class="btn btn-warning">Chỉnh sửa</a>
      <a href="{{ route('admin.users.index') }}" class="btn btn-secondary">Quay lại danh sách</a>
      <form action="{{ route('admin.users.destroy', $user) }}" method="POST" class="d-inline-block" onsubmit="return confirm('Bạn có chắc chắn muốn xóa người dùng này?');">
        @csrf
        @method('DELETE')
        <button type="submit" class="btn btn-danger">Xóa</button>
      </form>
    </div>
  </div>
</div>
@endsection

✅ 6. (Tùy chọn) Quản lý permission theo role

Tạo file database/seeders/PermissionSeeder.php

<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
class PermissionSeeder extends Seeder
{
  public function run()
  {
    $permissions = [
      'page.view',
      'page.create',
      'page.edit',
      'page.delete',
      'user.view',
      'user.create',
      'user.edit',
      'user.delete',
      'role.view',
      'role.create',
      'role.edit',
      'role.delete',
    ];
    foreach ($permissions as $permission) {
      Permission::firstOrCreate(['name' => $permission]);
    }
    $admin = Role::firstOrCreate(['name' => 'admin']);
    $editor = Role::firstOrCreate(['name' => 'editor']);
    $admin->givePermissionTo(Permission::all());
    $editor->givePermissionTo([
      'page.view',
      'page.create',
      'page.edit',
    ]);
  }
}
Sau đó:
php artisan db:seed --class=PermissionSeeder

Middleware & Policy (global check)

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();

Trong App\Providers\AuthServiceProvider:

<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Models\Page;
use App\Policies\PagePolicy;
use Illuminate\Support\Facades\Gate;
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
  {
    // $this->registerPolicies();
    Gate::before(function ($user, $ability) {
      return $user->hasRole('admin') ? true : null;
  });
  }
}

Controller quản lý User / Role / Permission

php artisan make:controller Admin/UserController --resource
php artisan make:controller Admin/RoleController --resource

app\Http\Controllers\Admin\UserController.php

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Spatie\Permission\Models\Role;
use Illuminate\Support\Facades\Hash; // Cần dùng để mã hóa mật khẩu
class UserController extends Controller
{
  /**
   * Display a listing of the resource.
   */
  public function index()
  {
    // $users = User::all();
    // Lấy tất cả người dùng và eager load các vai trò của họ để tránh N+1 query
    $users = User::with('roles')->get();
    return view('admin.users.index', compact('users'));
  }
  /**
   * Show the form for creating a new resource.
   */
  public function create()
  {
    // Lấy tất cả các vai trò để hiển thị trên form tạo người dùng
    $roles = Role::all();
    return view('admin.users.create', compact('roles'));
  }
  /**
   * Store a newly created resource in storage.
   */
  public function store(Request $request)
  {
    // Validate dữ liệu đầu vào
    $request->validate([
      'name' => 'required|string|max:255',
      'email' => 'required|string|email|max:255|unique:users', // Email phải là duy nhất
      'password' => 'required|string|min:8|confirmed', // Password tối thiểu 8 ký tự và phải được xác nhận
      'roles' => 'nullable|array', // Vai trò là một mảng, có thể rỗng
      'roles.*' => 'exists:roles,name', // Mỗi vai trò trong mảng phải tồn tại trong bảng roles
    ]);
    // Tạo người dùng mới
    $user = User::create([
      'name' => $request->name,
      'email' => $request->email,
      'password' => Hash::make($request->password), // Mã hóa mật khẩu
    ]);
    // Gán vai trò cho người dùng nếu có
    if ($request->has('roles')) {
      $user->syncRoles($request->roles);
    }
    return redirect()->route('admin.users.index')->with('success', 'Tạo người dùng mới thành công.');
  }
  /**
   * Display the specified resource.
   */
  public function show(User $user) // Sử dụng Route Model Binding
  {
    // Lấy thông tin chi tiết của người dùng, bao gồm cả các vai trò của họ
    $user->load('roles');
    return view('admin.users.show', compact('user'));
  }
  /**
   * Show the form for editing the specified resource.
   */
  public function edit(User $user)
  {
    $roles = Role::all();
    return view('admin.users.edit', compact('user', 'roles'));
  }
  /**
   * Update the specified resource in storage.
   */
  public function update(Request $request, User $user)
  {
    // $request->validate([
    //   'roles' => 'array',
    // ]);
    // $user->syncRoles($request->roles);
    // return redirect()->route('admin.users.index')->with('success', 'Cập nhật vai trò thành công.');
    $request->validate([
      'name' => 'required|string|max:255',
      'email' => 'required|string|email|max:255|unique:users,email,' . $user->id, // Email phải là duy nhất, bỏ qua email của chính user này
      'password' => 'nullable|string|min:8|confirmed', // Mật khẩu có thể không thay đổi, hoặc thay đổi thì cần xác nhận
      'roles' => 'array',
      'roles.*' => 'exists:roles,name',
    ]);
    $user->update([
      'name' => $request->name,
      'email' => $request->email,
    ]);
    // Cập nhật mật khẩu nếu có
    if ($request->filled('password')) {
      $user->update([
        'password' => Hash::make($request->password),
      ]);
    }
    // Đồng bộ vai trò
    $user->syncRoles($request->roles);
    return redirect()->route('admin.users.index')->with('success', 'Cập nhật người dùng thành công.');
  }
  /**
   * Remove the specified resource from storage.
   */
  public function destroy(User $user)
  {
    // Bạn có thể thêm xác nhận hoặc kiểm tra quyền trước khi xóa
    $user->delete();
    return redirect()->route('admin.users.index')->with('success', 'Xóa người dùng thành công.');
  }
}

Giao diện Blade

resources\views\admin\users\create.blade.php

@extends('layouts.admin') {{-- Giả định bạn có layout admin --}}
@section('content')
<div class="container">
  <h1>Tạo người dùng mới</h1>
  @if ($errors->any())
  <div class="alert alert-danger">
    <ul>
      @foreach ($errors->all() as $error)
      <li>{{ $error }}</li>
      @endforeach
    </ul>
  </div>
  @endif
  <form action="{{ route('admin.users.store') }}" method="POST">
    @csrf
    <div class="mb-3">
      <label for="name" class="form-label">Tên người dùng:</label>
      <input type="text" class="form-control" id="name" name="name" value="{{ old('name') }}" required>
    </div>
    <div class="mb-3">
      <label for="email" class="form-label">Email:</label>
      <input type="email" class="form-control" id="email" name="email" value="{{ old('email') }}" required>
    </div>
    <div class="mb-3">
      <label for="password" class="form-label">Mật khẩu:</label>
      <input type="password" class="form-control" id="password" name="password" required>
    </div>
    <div class="mb-3">
      <label for="password_confirmation" class="form-label">Xác nhận mật khẩu:</label>
      <input type="password" class="form-control" id="password_confirmation" name="password_confirmation" required>
    </div>
    <div class="mb-3">
      <label class="form-label">Vai trò:</label>
      @foreach($roles as $role)
      <div class="form-check">
        <input class="form-check-input" type="checkbox" name="roles[]" value="{{ $role->name }}" id="role_{{ $role->id }}" {{ in_array($role->name, old('roles', [])) ? 'checked' : '' }}>
        <label class="form-check-label" for="role_{{ $role->id }}">
          {{ $role->name }}
        </label>
      </div>
      @endforeach
    </div>
    <button type="submit" class="btn btn-primary">Tạo người dùng</button>
    <a href="{{ route('admin.users.index') }}" class="btn btn-secondary">Hủy</a>
  </form>
</div>
@endsection

resources\views\admin\users\edit.blade.php

@extends('layouts.admin')
@section('content')
<div class="container mt-4">
  <h2>Phân quyền cho: {{ $user->email }}</h2>
  <form method="POST" action="{{ route('admin.users.update', $user) }}">
    @csrf
    @method('PUT')
    <div class="mb-3">
      <label class="form-label">Vai trò</label>
      @foreach($roles as $role)
        <div class="form-check">
          <input class="form-check-input" type="checkbox" name="roles[]" value="{{ $role->name }}"
            {{ $user->hasRole($role->name) ? 'checked' : '' }}>
          <label class="form-check-label">{{ $role->name }}</label>
        </div>
      @endforeach
    </div>
    <button type="submit" class="btn btn-primary">Cập nhật</button>
    <a href="{{ route('admin.users.index') }}" class="btn btn-secondary">Quay lại</a>
  </form>
</div>
@endsection

resources\views\admin\users\index.blade.php

@extends('layouts.admin')
@section('content')
<div class="container mt-4">
  <h2>Quản lý người dùng</h2>
  <table class="table">
    <thead>
      <tr>
        <th>Email</th>
        <th>Vai trò</th>
        <th>Thao tác</th>
      </tr>
    </thead>
    <tbody>
      @foreach($users as $user)
      <tr>
        <td>{{ $user->name }}</td>
        <td>{{ $user->email }}</td>
        <td>{{ $user->getRoleNames()->join(', ') }}</td>
        <td>
          <a href="{{ route('admin.users.edit', $user) }}" class="btn btn-sm btn-primary">Phân quyền</a>
          <form action="{{ route('admin.users.destroy', $user) }}" method="POST" class="d-inline-block" onsubmit="return confirm('Bạn có chắc chắn muốn xóa người dùng này?');">
            @csrf
            @method('DELETE')
            <button type="submit" class="btn btn-danger">Xóa</button>
          </form>
        </td>
      </tr>
      @endforeach
    </tbody>
  </table>
</div>
@endsection

resources\views\admin\users\show.blade.php

@extends('layouts.admin') {{-- Giả định bạn có layout admin --}}
@section('content')
<div class="container">
  <h1>Chi tiết người dùng: {{ $user->name }}</h1>
  <div class="card">
    <div class="card-body">
      <h5 class="card-title">ID: {{ $user->id }}</h5>
      <p class="card-text"><strong>Tên:</strong> {{ $user->name }}</p>
      <p class="card-text"><strong>Email:</strong> {{ $user->email }}</p>
      <p class="card-text"><strong>Ngày tạo:</strong> {{ $user->created_at->format('d/m/Y H:i') }}</p>
      <p class="card-text"><strong>Ngày cập nhật:</strong> {{ $user->updated_at->format('d/m/Y H:i') }}</p>
      <p class="card-text"><strong>Vai trò:</strong>
        @forelse ($user->roles as $role)
        <span class="badge bg-primary">{{ $role->name }}</span>
        @empty
        Không có vai trò nào.
        @endforelse
      </p>
      <a href="{{ route('admin.users.edit', $user) }}" class="btn btn-warning">Chỉnh sửa</a>
      <a href="{{ route('admin.users.index') }}" class="btn btn-secondary">Quay lại danh sách</a>
      <form action="{{ route('admin.users.destroy', $user) }}" method="POST" class="d-inline-block" onsubmit="return confirm('Bạn có chắc chắn muốn xóa người dùng này?');">
        @csrf
        @method('DELETE')
        <button type="submit" class="btn btn-danger">Xóa</button>
      </form>
    </div>
  </div>
</div>
@endsection

routes\admin.php

<?php
use App\Http\Controllers\Admin\PermissionController;
use App\Http\Controllers\Admin\RoleController;
use App\Http\Controllers\Admin\UserController;
use Illuminate\Support\Facades\Route;
Route::middleware(['auth'])->prefix('admin')->name('admin.')->group(function () {
  // Route::resource('users', UserController::class)->middleware('permission:manage users');
  Route::resource('users', UserController::class)->only(['index', 'edit', 'update', 'destroy', 'show', 'create', 'store'])->middleware('permission:manage users');
  Route::resource('users', UserController::class)->only(['index', 'edit', 'update', 'destroy', 'show'])->middleware('permission:edit users');
  Route::resource('roles', RoleController::class)->middleware('permission:manage roles');
  Route::resource('permissions', PermissionController::class)->only(['index']);
});

Middleware Kiểm Tra Quyền

Trong PageController, thêm middleware:

public function __construct()
{
    $this->middleware('permission:view pages')->only(['index', 'show']);
    $this->middleware('permission:create pages')->only(['create', 'store']);
    $this->middleware('permission:edit pages')->only(['edit', 'update']);
    $this->middleware('permission:delete pages')->only(['destroy']);
}

View: Giao diện danh sách quyền

resources\views\admin\permissions\index.blade.php

@extends('layouts.admin')
@section('content')
<div class="container">
  <h2 class="mb-4">Danh sách quyền (Permissions)</h2>
  <table class="table table-bordered">
    <thead>
      <tr>
        <th>#</th>
        <th>Tên quyền</th>
        <th>Ngày tạo</th>
      </tr>
    </thead>
    <tbody>
      @forelse ($permissions as $permission)
      <tr>
        <td>{{ $loop->iteration }}</td>
        <td>{{ $permission->name }}</td>
        <td>{{ $permission->created_at->format('d/m/Y') }}</td>
      </tr>
      @empty
      <tr>
        <td colspan="3">Không có quyền nào.</td>
      </tr>
      @endforelse
    </tbody>
  </table>
  {{-- <a href="{{ route('admin.dashboard') }}" class="btn btn-secondary mt-3">Quay lại</a> --}}
  <a href="#" class="btn btn-secondary mt-3">Quay lại</a>
</div>
@endsection

Gợi ý: Nếu bạn muốn thêm tính năng tạo, sửa, xóa permission, tôi có thể bổ sung thêm các action và giao diện tương ứng (form, validate,...).

https://chatgpt.com/c/683f0b40-af48-8003-9fd6-1c42fc60142f

Last updated

Was this helpful?