Laravel 12 User Roles and Permissions Tutorial

Laravel 12 User Roles and Permissions Tutorial

Introduction

Controlling user access is a key part of building secure web applications. In Laravel 12, you can easily manage this using the Spatie Laravel Permission package.

This step-by-step tutorial will guide beginners through:

  • ✅ Installing and setting up Spatie in a Laravel 12 project

  • 👥 Creating roles like Admin, Editor, and User

  • 🔐 Assigning permissions such as create, edit, delete, and view

  • 🔒 Restricting access in your Blade templates — no Livewire needed!

Whether you're building an admin dashboard or a multi-user platform, this guide will help you set up clean and powerful access control.

Step 1: Install Laravel 12

Start by creating a fresh Laravel 12 project. Open your terminal and run:

composer create-project laravel/laravel example-app

Step 2: Install Spatie Permission Package

To manage roles and permissions, install the Spatie package:

composer require spatie/laravel-permission

Then, publish the package’s configuration and migration files:

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

Update .env to connect with your database:

DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=laravel_db DB_USERNAME=root DB_PASSWORD=

Run migrations tables:

php artisan migrate

Step 3: Create Products Table

Generate a migration for the products table:

php artisan make:model Product -m

Edit the migration file:

Schema::create('products', function (Blueprint $table) { $table->id(); $table->string('name'); $table->text('detail'); $table->timestamps(); });

Run the migration:

php artisan migrate

Step 4: Create Models

Update the User Model to use roles:

app/Models/User.php

namespace App\Models; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Illuminate\Database\Eloquent\Factories\HasFactory; use Spatie\Permission\Traits\HasRoles; class User extends Authenticatable { use HasFactory, Notifiable, HasRoles; protected $fillable = ['name', 'email', 'password']; protected $hidden = ['password', 'remember_token']; protected function casts(): array { return [ 'email_verified_at' => 'datetime', 'password' => 'hashed', ]; } }

Create the Product model:

app/Models/Product.php

class Product extends Model { protected $fillable = ['name', 'detail']; }

Step 5: Register Middleware

Add Spatie’s role/permission middleware in bootstrap/app.php:

$middleware->alias([ 'role' => \Spatie\Permission\Middleware\RoleMiddleware::class, 'permission' => \Spatie\Permission\Middleware\PermissionMiddleware::class, 'role_or_permission' => \Spatie\Permission\Middleware\RoleOrPermissionMiddleware::class, ]);

Step 6: Set Up Authentication

Install Laravel UI and generate auth scaffolding:

composer require laravel/ui php artisan ui bootstrap --auth

Then compile the frontend:

npm install npm run build

Step 7: Define Routes

Add routes in routes/web.php for user, role, and product management:

<?php use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Auth; use App\Http\Controllers\HomeController; use App\Http\Controllers\RoleController; use App\Http\Controllers\UserController; use App\Http\Controllers\ProductController; // Redirect root URL to /home if logged in, or to login otherwise Route::get('/', function () { if (Auth::check()) { return redirect()->route('home'); } return redirect()->route('login'); // or return view('welcome'); }); // Auth routes (login, register, forgot password, etc.) Auth::routes(); // Home page after login Route::get('/home', [HomeController::class, 'index'])->name('home'); // Protected routes (only accessible when logged in) Route::middleware(['auth'])->group(function () { Route::resource('roles', RoleController::class); Route::resource('users', UserController::class); Route::resource('products', ProductController::class); });

Step 8: Create Controller

8.1. Create UserController

Run the following Artisan commands:

php artisan make:controller UserController

Create the file app/Http/Controllers/UserController.php With the following content:

<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\User; use Spatie\Permission\Models\Role; use DB; use Hash; use Illuminate\Support\Arr; use Illuminate\View\View; use Illuminate\Http\RedirectResponse; class UserController extends Controller { public function index(Request $request): View { $data = User::latest()->paginate(5); return view('users.index', compact('data')) ->with('i', ($request->input('page', 1) - 1) * 5); } public function create(): View { $roles = Role::pluck('name', 'name')->all(); return view('users.create', compact('roles')); } public function store(Request $request): RedirectResponse { $this->validate($request, [ 'name' => 'required', 'email' => 'required|email|unique:users,email', 'password' => 'required|same:confirm-password', 'roles' => 'required' ]); $input = $request->all(); $input['password'] = Hash::make($input['password']); $user = User::create($input); $user->assignRole($request->input('roles')); return redirect()->route('users.index') ->with('success', 'User created successfully'); } public function show($id): View { $user = User::find($id); return view('users.show', compact('user')); } public function edit($id): View { $user = User::find($id); $roles = Role::pluck('name', 'name')->all(); $userRole = $user->roles->pluck('name', 'name')->all(); return view('users.edit', compact('user', 'roles', 'userRole')); } public function update(Request $request, $id): RedirectResponse { $this->validate($request, [ 'name' => 'required', 'email' => 'required|email|unique:users,email,' . $id, 'password' => 'same:confirm-password', 'roles' => 'required' ]); $input = $request->all(); if (!empty($input['password'])) { $input['password'] = Hash::make($input['password']); } else { $input = Arr::except($input, array('password')); } $user = User::find($id); $user->update($input); DB::table('model_has_roles')->where('model_id', $id)->delete(); $user->assignRole($request->input('roles')); return redirect()->route('users.index') ->with('success', 'User updated successfully'); } public function destroy($id): RedirectResponse { User::find($id)->delete(); return redirect()->route('users.index') ->with('success', 'User deleted successfully'); } }

8.2. Create ProductController

Run the following Artisan commands:

php artisan make:controller ProductController

Create the file app/Http/Controllers/ProductController.php With the following content:

<?php namespace App\Http\Controllers; use App\Models\Product; use Illuminate\Http\Request; use Illuminate\View\View; use Illuminate\Http\RedirectResponse; class ProductController extends Controller { function __construct() { $this->middleware('permission:product-list|product-create|product-edit|product-delete', ['only' => ['index','show']]); $this->middleware('permission:product-create', ['only' => ['create','store']]); $this->middleware('permission:product-edit', ['only' => ['edit','update']]); $this->middleware('permission:product-delete', ['only' => ['destroy']]); } public function index(): View { $products = Product::latest()->paginate(5); return view('products.index', compact('products')) ->with('i', (request()->input('page', 1) - 1) * 5); } public function create(): View { return view('products.create'); } public function store(Request $request): RedirectResponse { request()->validate([ 'name' => 'required', 'detail' => 'required', ]); Product::create($request->all()); return redirect()->route('products.index') ->with('success', 'Product created successfully.'); } public function show(Product $product): View { return view('products.show', compact('product')); } public function edit(Product $product): View { return view('products.edit', compact('product')); } public function update(Request $request, Product $product): RedirectResponse { request()->validate([ 'name' => 'required', 'detail' => 'required', ]); $product->update($request->all()); return redirect()->route('products.index') ->with('success', 'Product updated successfully'); } public function destroy(Product $product): RedirectResponse { $product->delete(); return redirect()->route('products.index') ->with('success', 'Product deleted successfully'); } }

8.3. Create RoleController

Run the following Artisan commands:

php artisan make:controller RoleController

Create the file app/Http/Controllers/RoleController.php With the following content:

<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Spatie\Permission\Models\Role; use Spatie\Permission\Models\Permission; use DB; use Illuminate\View\View; use Illuminate\Http\RedirectResponse; class RoleController extends Controller { function __construct() { $this->middleware('permission:role-list|role-create|role-edit|role-delete', ['only' => ['index','store']]); $this->middleware('permission:role-create', ['only' => ['create','store']]); $this->middleware('permission:role-edit', ['only' => ['edit','update']]); $this->middleware('permission:role-delete', ['only' => ['destroy']]); } public function index(Request $request): View { $roles = Role::orderBy('id', 'DESC')->paginate(5); return view('roles.index', compact('roles')) ->with('i', ($request->input('page', 1) - 1) * 5); } public function create(): View { $permission = Permission::get(); return view('roles.create', compact('permission')); } public function store(Request $request): RedirectResponse { $this->validate($request, [ 'name' => 'required|unique:roles,name', 'permission' => 'required', ]); $permissionsID = array_map(function ($value) { return (int)$value; }, $request->input('permission')); $role = Role::create(['name' => $request->input('name')]); $role->syncPermissions($permissionsID); return redirect()->route('roles.index') ->with('success', 'Role created successfully'); } public function show($id): View { $role = Role::find($id); $rolePermissions = Permission::join("role_has_permissions", "role_has_permissions.permission_id", "=", "permissions.id") ->where("role_has_permissions.role_id", $id) ->get(); return view('roles.show', compact('role', 'rolePermissions')); } public function edit($id): View { $role = Role::find($id); $permission = Permission::get(); $rolePermissions = DB::table("role_has_permissions")->where("role_has_permissions.role_id", $id) ->pluck('role_has_permissions.permission_id', 'role_has_permissions.permission_id') ->all(); return view('roles.edit', compact('role', 'permission', 'rolePermissions')); } public function update(Request $request, $id): RedirectResponse { $this->validate($request, [ 'name' => 'required', 'permission' => 'required', ]); $role = Role::find($id); $role->name = $request->input('name'); $role->save(); $permissionsID = array_map(function ($value) { return (int)$value; }, $request->input('permission')); $role->syncPermissions($permissionsID); return redirect()->route('roles.index') ->with('success', 'Role updated successfully'); } public function destroy($id): RedirectResponse { DB::table("roles")->where('id', $id)->delete(); return redirect()->route('roles.index') ->with('success', 'Role deleted successfully'); } }

Step 9: Add Blade Files

Create the main layout file

Update the file:

resources/views/layouts/app.blade.php

<!doctype html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- CSRF Token --> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>{{ config('app.name', 'Laravel') }}</title> <!-- Fonts --> <link rel="dns-prefetch" href="//fonts.bunny.net"> <link href="https://fonts.bunny.net/css?family=Nunito" rel="stylesheet"> <!-- Scripts --> @vite(['resources/sass/app.scss', 'resources/js/app.js']) <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" /> </head> <body> <div id="app"> <nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm"> <div class="container"> <a class="navbar-brand" href="{{ url('/') }}"> StarCode Kh </a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <!-- Left Side Of Navbar --> <ul class="navbar-nav me-auto"></ul> <!-- Right Side Of Navbar --> <ul class="navbar-nav ms-auto"> <!-- Authentication Links --> @guest @if (Route::has('login')) <li class="nav-item"> <a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a> </li> @endif @if (Route::has('register')) <li class="nav-item"> <a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a> </li> @endif @else <li><a class="nav-link" href="{{ route('users.index') }}">Manage Users</a></li> <li><a class="nav-link" href="{{ route('roles.index') }}">Manage Role</a></li> <li><a class="nav-link" href="{{ route('products.index') }}">Manage Product</a></li> <li class="nav-item dropdown"> <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre> {{ Auth::user()->name }} </a> <div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown"> <a class="dropdown-item" href="{{ route('logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();"> {{ __('Logout') }} </a> <form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none"> @csrf </form> </div> </li> @endguest </ul> </div> </div> </nav> <main class="py-4"> <div class="container"> <div class="row justify-content-center"> <div class="col-md-12"> <div class="card"> <div class="card-body"> @yield('content') </div> </div> </div> </div> </div> </main> </div> </body> </html>

resources/views/users/index.blade.php

@extends('layouts.app') @section('content') <div class="row mb-3"> <div class="col-lg-12 d-flex justify-content-between align-items-center"> <h2 class="mb-0">Users Management</h2> @can('role-create') <a class="btn btn-success btn-sm" href="{{ route('users.create') }}"> <i class="fa fa-plus"></i> Create New User </a> @endcan </div> </div> @session('success') <div class="alert alert-success" role="alert"> {{ $value }} </div> @endsession <table class="table table-bordered"> <tr> <th>No</th> <th>Name</th> <th>Email</th> <th>Roles</th> <th width="280px">Action</th> </tr> @foreach ($data as $key => $user) <tr> <td>{{ ++$i }}</td> <td>{{ $user->name }}</td> <td>{{ $user->email }}</td> <td> @if(!empty($user->getRoleNames())) @foreach($user->getRoleNames() as $v) <label class="badge bg-success">{{ $v }}</label> @endforeach @endif </td> <td> <a class="btn btn-info btn-sm" href="{{ route('users.show',$user->id) }}"> <i class="fa-solid fa-list"></i> Show </a> <a class="btn btn-primary btn-sm" href="{{ route('users.edit',$user->id) }}"> <i class="fa-solid fa-pen-to-square"></i> Edit </a> <form method="POST" action="{{ route('users.destroy', $user->id) }}" style="display:inline"> @csrf @method('DELETE') <button type="submit" class="btn btn-danger btn-sm"> <i class="fa-solid fa-trash"></i> Delete </button> </form> </td> </tr> @endforeach </table> {!! $data->links('pagination::bootstrap-5') !!} @endsection

resources/views/users/create.blade.php

@extends('layouts.app') @section('content') <div class="row"> <div class="col-lg-12 margin-tb"> <div class="pull-left"> <h2>Create New User</h2> </div> <div class="pull-right"> <a class="btn btn-primary btn-sm mb-2" href="{{ route('users.index') }}"> <i class="fa fa-arrow-left"></i> Back </a> </div> </div> </div> @if (count($errors) > 0) <div class="alert alert-danger"> <strong>Whoops!</strong> There were some problems with your input.<br><br> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <form method="POST" action="{{ route('users.store') }}"> @csrf <div class="row"> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Name:</strong> <input type="text" name="name" placeholder="Name" class="form-control"> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Email:</strong> <input type="email" name="email" placeholder="Email" class="form-control"> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Password:</strong> <input type="password" name="password" placeholder="Password" class="form-control"> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Confirm Password:</strong> <input type="password" name="confirm-password" placeholder="Confirm Password" class="form-control"> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Role:</strong> <select name="roles[]" class="form-control" multiple="multiple"> @foreach ($roles as $value => $label) <option value="{{ $value }}"> {{ $label }} </option> @endforeach </select> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12 text-center"> <button type="submit" class="btn btn-primary btn-sm mt-2 mb-3"> <i class="fa-solid fa-floppy-disk"></i> Submit </button> </div> </div> </form> @endsection

resources/views/users/edit.blade.php

@extends('layouts.app') @section('content') <div class="row"> <div class="col-lg-12 margin-tb d-flex justify-content-between align-items-center"> <h2>Edit User</h2> <a class="btn btn-primary btn-sm" href="{{ route('users.index') }}"> <i class="fa fa-arrow-left"></i> Back </a> </div> </div> @if ($errors->any()) <div class="alert alert-danger mt-2"> <strong>Whoops!</strong> There were some problems with your input.<br><br> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <form method="POST" action="{{ route('users.update', $user->id) }}"> @csrf @method('PUT') <div class="row mt-3"> <div class="col-12 mb-3"> <label><strong>Name:</strong></label> <input type="text" name="name" class="form-control" placeholder="Name" value="{{ old('name', $user->name) }}"> </div> <div class="col-12 mb-3"> <label><strong>Email:</strong></label> <input type="email" name="email" class="form-control" placeholder="Email" value="{{ old('email', $user->email) }}"> </div> <div class="col-12 mb-3"> <label><strong>Password:</strong></label> <input type="password" name="password" class="form-control" placeholder="Password"> </div> <div class="col-12 mb-3"> <label><strong>Confirm Password:</strong></label> <input type="password" name="confirm-password" class="form-control" placeholder="Confirm Password"> </div> <div class="col-12 mb-3"> <label><strong>Role:</strong></label> <select name="roles[]" class="form-control" multiple> @foreach ($roles as $value => $label) <option value="{{ $value }}" {{ isset($userRole[$value]) ? 'selected' : '' }}> {{ $label }} </option> @endforeach </select> </div> <div class="col-12 text-center"> <button type="submit" class="btn btn-primary btn-sm"> <i class="fa-solid fa-floppy-disk"></i> Submit </button> </div> </div> </form> @endsection

resources/views/users/show.blade.php

@extends('layouts.app') @section('content') <div class="row mb-3"> <div class="col-lg-12 d-flex justify-content-between align-items-center"> <h2>Show User</h2> <a class="btn btn-primary btn-sm" href="{{ route('users.index') }}">Back</a> </div> </div> <div class="row"> <div class="col-12 mb-3"> <strong>Name:</strong> <p>{{ $user->name }}</p> </div> <div class="col-12 mb-3"> <strong>Email:</strong> <p>{{ $user->email }}</p> </div> <div class="col-12"> <strong>Roles:</strong><br> @if($user->getRoleNames()->isNotEmpty()) @foreach ($user->getRoleNames() as $role) <span class="badge badge-success">{{ $role }}</span> @endforeach @else <p>No Roles Assigned</p> @endif </div> </div> @endsection

resources/views/roles/index.blade.php

@extends('layouts.app') @section('content') <div class="row mb-3"> <div class="col-lg-12 d-flex justify-content-between align-items-center"> <h2>Role Management</h2> @can('role-create') <a class="btn btn-success btn-sm" href="{{ route('roles.create') }}"> <i class="fa fa-plus"></i> Create New Role </a> @endcan </div> </div> @if(session('success')) <div class="alert alert-success"> {{ session('success') }} </div> @endif <table class="table table-bordered"> <thead> <tr> <th width="100px">No</th> <th>Name</th> <th width="280px">Action</th> </tr> </thead> <tbody> @foreach ($roles as $key => $role) <tr> <td>{{ $loop->iteration }}</td> <td>{{ $role->name }}</td> <td> <a class="btn btn-info btn-sm" href="{{ route('roles.show', $role->id) }}"> <i class="fa-solid fa-list"></i> Show </a> @can('role-edit') <a class="btn btn-primary btn-sm" href="{{ route('roles.edit', $role->id) }}"> <i class="fa-solid fa-pen-to-square"></i> Edit </a> @endcan @can('role-delete') <form method="POST" action="{{ route('roles.destroy', $role->id) }}" class="d-inline"> @csrf @method('DELETE') <button type="submit" class="btn btn-danger btn-sm"> <i class="fa-solid fa-trash"></i> Delete </button> </form> @endcan </td> </tr> @endforeach </tbody> </table> {!! $roles->links('pagination::bootstrap-5') !!} @endsection

resources/views/roles/create.blade.php

@extends('layouts.app') @section('content') <div class="row mb-3"> <div class="col-lg-12 d-flex justify-content-between align-items-center"> <h2>Create New Role</h2> <a class="btn btn-primary btn-sm" href="{{ route('roles.index') }}"> <i class="fa fa-arrow-left"></i> Back </a> </div> </div> @if ($errors->any()) <div class="alert alert-danger"> <strong>Whoops!</strong> There were some problems with your input.<br><br> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <form method="POST" action="{{ route('roles.store') }}"> @csrf <div class="row"> <div class="col-12 mb-3"> <label><strong>Name:</strong></label> <input type="text" name="name" class="form-control" placeholder="Name" value="{{ old('name') }}"> </div> <div class="col-12 mb-3"> <label><strong>Permission:</strong></label><br> @foreach($permission as $perm) <label> <input type="checkbox" name="permission[{{ $perm->id }}]" value="{{ $perm->id }}" class="me-1"> {{ $perm->name }} </label><br> @endforeach </div> <div class="col-12 text-center"> <button type="submit" class="btn btn-primary btn-sm"> <i class="fa-solid fa-floppy-disk"></i> Submit </button> </div> </div> </form> @endsection

resources/views/roles/edit.blade.php

@extends('layouts.app') @section('content') <div class="row"> <div class="col-lg-12 margin-tb"> <div class="pull-left"> <h2>Edit Role</h2> </div> <div class="pull-right"> <a class="btn btn-primary btn-sm mb-2" href="{{ route('roles.index') }}"><i class="fa fa-arrow-left"></i> Back</a> </div> </div> </div> @if (count($errors) > 0) <div class="alert alert-danger"> <strong>Whoops!</strong> There were some problems with your input.<br><br> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <form method="POST" action="{{ route('roles.update', $role->id) }}"> @csrf @method('PUT') <div class="row"> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Name:</strong> <input type="text" name="name" placeholder="Name" class="form-control" value="{{ $role->name }}"> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Permission:</strong> <br/> @foreach($permission as $value) <label> <input type="checkbox" name="permission[{{$value->id}}]" value="{{$value->id}}" class="name" {{ in_array($value->id, $rolePermissions) ? 'checked' : '' }}> {{ $value->name }} </label> <br/> @endforeach </div> </div> <div class="col-xs-12 col-sm-12 col-md-12 text-center"> <button type="submit" class="btn btn-primary btn-sm mb-3"> <i class="fa-solid fa-floppy-disk"></i> Submit </button> </div> </div> </form> @endsection

resources/views/roles/show.blade.php

@extends('layouts.app') @section('content') <div class="row mb-4"> <div class="col-lg-12 d-flex justify-content-between align-items-center"> <h2>Show Role</h2> <a class="btn btn-primary" href="{{ route('roles.index') }}">Back</a> </div> </div> <div class="row"> <div class="col-md-12 mb-3"> <div class="form-group"> <strong>Name:</strong> {{ $role->name }} </div> </div> <div class="col-md-12"> <div class="form-group"> <strong>Permissions:</strong> @if (!empty($rolePermissions)) @foreach ($rolePermissions as $permission) <span class="badge bg-success">{{ $permission->name }}</span> @endforeach @else <span>No permissions assigned.</span> @endif </div> </div> </div> @endsection

resources/views/products/index.blade.php

@extends('layouts.app') @section('content') <div class="row"> <div class="col-lg-12 margin-tb d-flex justify-content-between align-items-center mb-3"> <h2>Products</h2> @can('product-create') <a class="btn btn-success btn-sm" href="{{ route('products.create') }}"> <i class="fa fa-plus"></i> Create New Product </a> @endcan </div> </div> @if ($message = Session::get('success')) <div class="alert alert-success" role="alert"> {{ $message }} </div> @endif @php $i = ($products->currentPage() - 1) * $products->perPage(); @endphp <div class="table-responsive"> <table class="table table-bordered"> <tr> <th>No</th> <th>Name</th> <th>Details</th> <th width="280px">Action</th> </tr> @foreach ($products as $product) <tr> <td>{{ ++$i }}</td> <td>{{ $product->name }}</td> <td>{{ $product->detail }}</td> <td> <form action="{{ route('products.destroy',$product->id) }}" method="POST"> <a class="btn btn-info btn-sm" href="{{ route('products.show',$product->id) }}"> <i class="fa-solid fa-list"></i> Show </a> @can('product-edit') <a class="btn btn-primary btn-sm" href="{{ route('products.edit',$product->id) }}"> <i class="fa-solid fa-pen-to-square"></i> Edit </a> @endcan @csrf @method('DELETE') @can('product-delete') <button type="submit" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure?')"> <i class="fa-solid fa-trash"></i> Delete </button> @endcan </form> </td> </tr> @endforeach </table> </div> {!! $products->links() !!} @endsection

resources/views/products/create.blade.php

@extends('layouts.app') @section('content') <div class="row"> <div class="col-lg-12 margin-tb"> <div class="pull-left"> <h2>Add New Product</h2> </div> <div class="pull-right"> <a class="btn btn-primary btn-sm" href="{{ route('products.index') }}"> <i class="fa fa-arrow-left"></i> Back </a> </div> </div> </div> @if ($errors->any()) <div class="alert alert-danger"> <strong>Whoops!</strong> There were some problems with your input.<br><br> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <form action="{{ route('products.store') }}" method="POST"> @csrf <div class="row"> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Name:</strong> <input type="text" name="name" class="form-control" placeholder="Name"> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Detail:</strong> <textarea class="form-control" style="height:150px" name="detail" placeholder="Detail"></textarea> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12 text-center"> <button type="submit" class="btn btn-primary btn-sm mb-3 mt-2"> <i class="fa-solid fa-floppy-disk"></i> Submit </button> </div> </div> </form> @endsection

resources/views/products/edit.blade.php

@extends('layouts.app') @section('content') <div class="row"> <div class="col-lg-12 margin-tb"> <div class="pull-left"> <h2>Edit Product</h2> </div> <div class="pull-right"> <a class="btn btn-primary btn-sm mb-2" href="{{ route('products.index') }}"> <i class="fa fa-arrow-left"></i> Back </a> </div> </div> </div> @if ($errors->any()) <div class="alert alert-danger"> <strong>Whoops!</strong> There were some problems with your input.<br><br> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <form action="{{ route('products.update', $product->id) }}" method="POST"> @csrf @method('PUT') <div class="row"> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Name:</strong> <input type="text" name="name" value="{{ $product->name }}" class="form-control" placeholder="Name"> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Detail:</strong> <textarea class="form-control" style="height:150px" name="detail" placeholder="Detail">{{ $product->detail }}</textarea> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12 text-center"> <button type="submit" class="btn btn-primary btn-sm mb-2 mt-2"> <i class="fa-solid fa-floppy-disk"></i> Submit </button> </div> </div> </form> @endsection

resources/views/products/show.blade.php

@extends('layouts.app') @section('content') <div class="row"> <div class="col-lg-12 margin-tb"> <div class="pull-left"> <h2>Show Product</h2> </div> <div class="pull-right"> <a class="btn btn-primary" href="{{ route('products.index') }}">Back</a> </div> </div> </div> <div class="row mt-3"> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Name:</strong> {{ $product->name }} </div> </div> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Details:</strong> {{ $product->detail }} </div> </div> </div> @endsection

Step 10: Create Seeder For Permissions and AdminUser

In this step, we create seeders to add fixed permissions and an admin user with the Admin role.

1. Create Permission Seeder

Run this command to generate the seeder:

php artisan make:seeder PermissionTableSeeder

Then, add this code to database/seeders/PermissionTableSeeder.php:

<?php namespace Database\Seeders; use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; use Spatie\Permission\Models\Permission; class PermissionTableSeeder extends Seeder { /** * Run the database seeds. */ public function run(): void { $permissions = [ 'role-list', 'role-create', 'role-edit', 'role-delete', 'product-list', 'product-create', 'product-edit', 'product-delete' ]; foreach ($permissions as $permission) { Permission::create(['name' => $permission]); } } }

Run the seeder with:

php artisan db:seed --class=PermissionTableSeeder

2. Create Admin User Seeder

Generate the seeder:

php artisan make:seeder CreateAdminUserSeeder

Add this code to database/seeders/CreateAdminUserSeeder.php:

<?php namespace Database\Seeders; use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; use App\Models\User; use Spatie\Permission\Models\Role; use Spatie\Permission\Models\Permission; class CreateAdminUserSeeder extends Seeder { /** * Run the database seeds. */ public function run(): void { $user = User::create([ 'name' => 'Admin', 'email' => 'admin@gmail.com', 'password' => bcrypt('12345678') ]); $role = Role::create(['name' => 'Admin']); $permissions = Permission::pluck('id','id')->all(); $role->syncPermissions($permissions); $user->assignRole([$role->id]); } }

Run the seeder with:

php artisan db:seed --class=CreateAdminUserSeeder

3. Run Laravel App

Finally, start your Laravel server:

php artisan serve

Visit your app at http://localhost:8000

Souy Soeng

Souy Soeng

Hi there 👋, I’m Soeng Souy (StarCode Kh)
-------------------------------------------
🌱 I’m currently creating a sample Laravel and React Vue Livewire
👯 I’m looking to collaborate on open-source PHP & JavaScript projects
💬 Ask me about Laravel, MySQL, or Flutter
⚡ Fun fact: I love turning ☕️ into code!

Post a Comment

CAN FEEDBACK
close