Laravel 5.6 - User Roles and Permissions (ACL) using Spatie Tutorial

By Hardik Savani November 5, 2023 Category : PHP Laravel

ACL stands for Access Control List. ACL roles and permissions are very important if you are making big application in laravel 5.6. this tutorial will explain how to implement User Roles and Permissions(ACL) using spatie/laravel-permission composer package. So basically i will do it from scratch how to create permissions, roles, and users with assign roles etc.

I also posted on tutorial for ACL User Roles and Permissions using entrust package, you can see here : Laravel 5 - User Roles and Permissions (ACL) using entrust package.

If you are work on big ERP or Project then you need to control access to certain sections of the website. I mean you require to role permissions based access control database design that way you can specify the level of the user.

Roles and Permissions through you can create several types of users with different role and permission, i mean some user have only see a listing of items module, some user can also edit items modules, for delete and etc.

In this examples I created three modules as listed below:

User Management

Role Management

Product Management

After register user, you don't have any roles, so you can edit your details and assign admin role to you from User Management. After that you can create your own role with permission like role-list, role-create, role-edit, role-delete, product-list, product-create, product-edit, product-delete. you can check with assign new user and check that.

You need to just follow few step and you will get full example of ACL:

Step 1: Laravel 5.6 Installation

We are going from scratch so, If you haven't installed laravel in your system then you can run bellow command and get fresh Laravel project.

composer create-project --prefer-dist laravel/laravel blog

After clone laravel application, we also require to install laravelcollective/html for Form class, you can install from here : HTML/FORM not found in Laravel 5?..

Step 2: Spatie Package Installation

Now we require to install Spatie package for ACL, that way we can use it's method. So Open your terminal and run bellow command.

composer require spatie/laravel-permission

Now open config/app.php file and add service provider and aliase.

config/app.php

'providers' => [

....

Spatie\Permission\PermissionServiceProvider::class,

],

We can also custom changes on Spatie package, so if you also want to changes then you can fire bellow command and get config file in config/permission.php.

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

php artisan migrate

Step 3: Create Table using Migrations

In this step we have to create three migrations for as listed bellow tables:

1. users

2. products

3. roles

4. permissions

5. model_has_permissions

6. model_has_roles

7. role_has_permissions

So, if you install fresh project then you have already users table migration but if you don't have products table, so can create manually and other table can create using Spatie package command, so run bellow command and check migration file also.

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

php artisan make:migrate create_products_table

users table:

<?php


use Illuminate\Support\Facades\Schema;

use Illuminate\Database\Schema\Blueprint;

use Illuminate\Database\Migrations\Migration;


class CreateUsersTable extends Migration

{

/**

* Run the migrations.

*

* @return void

*/

public function up()

{

Schema::create('users', function (Blueprint $table) {

$table->increments('id');

$table->string('name');

$table->string('email');

$table->string('password');

$table->rememberToken();

$table->timestamps();

});

}


/**

* Reverse the migrations.

*

* @return void

*/

public function down()

{

Schema::dropIfExists('users');

}

}

products table:

<?php


use Illuminate\Support\Facades\Schema;

use Illuminate\Database\Schema\Blueprint;

use Illuminate\Database\Migrations\Migration;


class CreateProductsTable extends Migration

{

/**

* Run the migrations.

*

* @return void

*/

public function up()

{

Schema::create('products', function (Blueprint $table) {

$table->increments('id');

$table->string('name');

$table->text('detail');

$table->timestamps();

});

}


/**

* Reverse the migrations.

*

* @return void

*/

public function down()

{

Schema::dropIfExists('products');

}

}

Spatie tables:

<?php


use Illuminate\Support\Facades\Schema;

use Illuminate\Database\Schema\Blueprint;

use Illuminate\Database\Migrations\Migration;


class CreatePermissionTables extends Migration

{

/**

* Run the migrations.

*

* @return void

*/

public function up()

{

$tableNames = config('permission.table_names');


Schema::create($tableNames['permissions'], function (Blueprint $table) {

$table->increments('id');

$table->string('name');

$table->string('guard_name');

$table->timestamps();

});


Schema::create($tableNames['roles'], function (Blueprint $table) {

$table->increments('id');

$table->string('name');

$table->string('guard_name');

$table->timestamps();

});


Schema::create($tableNames['model_has_permissions'], function (Blueprint $table) use ($tableNames) {

$table->integer('permission_id')->unsigned();

$table->morphs('model');


$table->foreign('permission_id')

->references('id')

->on($tableNames['permissions'])

->onDelete('cascade');


$table->primary(['permission_id', 'model_id', 'model_type']);

});


Schema::create($tableNames['model_has_roles'], function (Blueprint $table) use ($tableNames) {

$table->integer('role_id')->unsigned();

$table->morphs('model');


$table->foreign('role_id')

->references('id')

->on($tableNames['roles'])

->onDelete('cascade');


$table->primary(['role_id', 'model_id', 'model_type']);

});


Schema::create($tableNames['role_has_permissions'], function (Blueprint $table) use ($tableNames) {

$table->integer('permission_id')->unsigned();

$table->integer('role_id')->unsigned();


$table->foreign('permission_id')

->references('id')

->on($tableNames['permissions'])

->onDelete('cascade');


$table->foreign('role_id')

->references('id')

->on($tableNames['roles'])

->onDelete('cascade');


$table->primary(['permission_id', 'role_id']);


app('cache')->forget('spatie.permission.cache');

});

}


/**

* Reverse the migrations.

*

* @return void

*/

public function down()

{

$tableNames = config('permission.table_names');


Schema::drop($tableNames['role_has_permissions']);

Schema::drop($tableNames['model_has_roles']);

Schema::drop($tableNames['model_has_permissions']);

Schema::drop($tableNames['roles']);

Schema::drop($tableNames['permissions']);

}

}

Step 4: Create Table Models

In this step we have to create model for User and Product table, so if you get fresh project then you have User Model have so just replace code and other you should create.

app/User.php

<?php


namespace App;


use Illuminate\Notifications\Notifiable;

use Laravel\Passport\HasApiTokens;

use Illuminate\Foundation\Auth\User as Authenticatable;

use Spatie\Permission\Traits\HasRoles;


class User extends Authenticatable

{

use HasApiTokens, Notifiable;

use HasRoles;


/**

* The attributes that are mass assignable.

*

* @var array

*/

protected $fillable = [

'name', 'email', 'password',

];


/**

* The attributes that should be hidden for arrays.

*

* @var array

*/

protected $hidden = [

'password', 'remember_token',

];

}

app/Product.php

<?php


namespace App;


use Illuminate\Database\Eloquent\Model;


class Product extends Model

{

/**

* The attributes that are mass assignable.

*

* @var array

*/

protected $fillable = [

'name', 'detail'

];

}

Step 5: Add Middleware

Spatie package provide it's in-built middleware that way we can use it simply and that is display as bellow:

role

permission

So, we have to add middleware in Kernel.php file this way :

app/Http/Kernel.php

....

protected $routeMiddleware = [

....

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

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

]

....

Step 6: Create Seeder For Permissions

In this step we will create seeder for permissions, Right now we have fixed permission so we create using seeder as listed bellow, but if you can add more permission as you want:

1.role-list

2.role-create

3.role-edit

4.role-delete

5.product-list

6.product-create

7.product-edit

8.product-delete

So, first create seeder using bellow command:

php artisan make:seeder PermissionTableSeeder

And put bellow code in PermissionTableSeeder seeder this way:

database/seeds/PermissionTableSeeder.php

<?php


use Illuminate\Database\Seeder;

use Spatie\Permission\Models\Permission;


class PermissionTableSeeder extends Seeder

{

/**

* Run the database seeds.

*

* @return void

*/

public function run()

{

$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]);

}

}

}

After this we have to run bellow command for run PermissionTableSeeder seeder:

php artisan db:seed --class=PermissionTableSeeder

Step 7: Create Authentication

In this step we require to create authentication of Laravel 5.6, so laravel provide artisan command to create authentication that way we don't require to create route and controller for login and registration. so run bellow command:

php artisan make:auth

Step 8: Create Routes

We require to add number of route for users module, products module and roles module. In this this route i also use middleware with permission for roles and products route, so add route this way:

routes/web.php

Auth::routes();


Route::get('/home', 'HomeController@index')->name('home');


Route::group(['middleware' => ['auth']], function() {

Route::resource('roles','RoleController');

Route::resource('users','UserController');

Route::resource('products','ProductController');

});

Step 9: Add Controllers

In this step we have add three controller for users module, products module and roles module so you can create three controller like as bellow:

app/Http/Controllers/UserController.php

<?php


namespace App\Http\Controllers;


use Illuminate\Http\Request;

use App\Http\Controllers\Controller;

use App\User;

use Spatie\Permission\Models\Role;

use DB;

use Hash;


class UserController extends Controller

{

/**

* Display a listing of the resource.

*

* @return \Illuminate\Http\Response

*/

public function index(Request $request)

{

$data = User::orderBy('id','DESC')->paginate(5);

return view('users.index',compact('data'))

->with('i', ($request->input('page', 1) - 1) * 5);

}


/**

* Show the form for creating a new resource.

*

* @return \Illuminate\Http\Response

*/

public function create()

{

$roles = Role::pluck('name','name')->all();

return view('users.create',compact('roles'));

}


/**

* Store a newly created resource in storage.

*

* @param \Illuminate\Http\Request $request

* @return \Illuminate\Http\Response

*/

public function store(Request $request)

{

$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');

}


/**

* Display the specified resource.

*

* @param int $id

* @return \Illuminate\Http\Response

*/

public function show($id)

{

$user = User::find($id);

return view('users.show',compact('user'));

}


/**

* Show the form for editing the specified resource.

*

* @param int $id

* @return \Illuminate\Http\Response

*/

public function edit($id)

{

$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'));

}


/**

* Update the specified resource in storage.

*

* @param \Illuminate\Http\Request $request

* @param int $id

* @return \Illuminate\Http\Response

*/

public function update(Request $request, $id)

{

$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 = array_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');

}


/**

* Remove the specified resource from storage.

*

* @param int $id

* @return \Illuminate\Http\Response

*/

public function destroy($id)

{

User::find($id)->delete();

return redirect()->route('users.index')

->with('success','User deleted successfully');

}

}

app/Http/Controllers/ProductController.php

<?php


namespace App\Http\Controllers;


use App\Product;

use Illuminate\Http\Request;


class ProductController extends Controller

{

/**

* Display a listing of the resource.

*

* @return \Illuminate\Http\Response

*/

function __construct()

{

$this->middleware('permission:product-list');

$this->middleware('permission:product-create', ['only' => ['create','store']]);

$this->middleware('permission:product-edit', ['only' => ['edit','update']]);

$this->middleware('permission:product-delete', ['only' => ['destroy']]);

}

/**

* Display a listing of the resource.

*

* @return \Illuminate\Http\Response

*/

public function index()

{

$products = Product::latest()->paginate(5);

return view('products.index',compact('products'))

->with('i', (request()->input('page', 1) - 1) * 5);

}


/**

* Show the form for creating a new resource.

*

* @return \Illuminate\Http\Response

*/

public function create()

{

return view('products.create');

}


/**

* Store a newly created resource in storage.

*

* @param \Illuminate\Http\Request $request

* @return \Illuminate\Http\Response

*/

public function store(Request $request)

{

request()->validate([

'name' => 'required',

'detail' => 'required',

]);


Product::create($request->all());


return redirect()->route('products.index')

->with('success','Product created successfully.');

}


/**

* Display the specified resource.

*

* @param \App\Product $product

* @return \Illuminate\Http\Response

*/

public function show(Product $product)

{

return view('products.show',compact('product'));

}


/**

* Show the form for editing the specified resource.

*

* @param \App\Product $product

* @return \Illuminate\Http\Response

*/

public function edit(Product $product)

{

return view('products.edit',compact('product'));

}


/**

* Update the specified resource in storage.

*

* @param \Illuminate\Http\Request $request

* @param \App\Product $product

* @return \Illuminate\Http\Response

*/

public function update(Request $request, Product $product)

{

request()->validate([

'name' => 'required',

'detail' => 'required',

]);


$product->update($request->all());


return redirect()->route('products.index')

->with('success','Product updated successfully');

}


/**

* Remove the specified resource from storage.

*

* @param \App\Product $product

* @return \Illuminate\Http\Response

*/

public function destroy(Product $product)

{

$product->delete();


return redirect()->route('products.index')

->with('success','Product deleted successfully');

}

}

app/Http/Controllers/RoleController.php

<?php


namespace App\Http\Controllers;


use Illuminate\Http\Request;

use App\Http\Controllers\Controller;

use Spatie\Permission\Models\Role;

use Spatie\Permission\Models\Permission;

use DB;


class RoleController extends Controller

{

/**

* Display a listing of the resource.

*

* @return \Illuminate\Http\Response

*/

function __construct()

{

$this->middleware('permission:role-list');

$this->middleware('permission:role-create', ['only' => ['create','store']]);

$this->middleware('permission:role-edit', ['only' => ['edit','update']]);

$this->middleware('permission:role-delete', ['only' => ['destroy']]);

}


/**

* Display a listing of the resource.

*

* @return \Illuminate\Http\Response

*/

public function index(Request $request)

{

$roles = Role::orderBy('id','DESC')->paginate(5);

return view('roles.index',compact('roles'))

->with('i', ($request->input('page', 1) - 1) * 5);

}


/**

* Show the form for creating a new resource.

*

* @return \Illuminate\Http\Response

*/

public function create()

{

$permission = Permission::get();

return view('roles.create',compact('permission'));

}


/**

* Store a newly created resource in storage.

*

* @param \Illuminate\Http\Request $request

* @return \Illuminate\Http\Response

*/

public function store(Request $request)

{

$this->validate($request, [

'name' => 'required|unique:roles,name',

'permission' => 'required',

]);


$role = Role::create(['name' => $request->input('name')]);

$role->syncPermissions($request->input('permission'));


return redirect()->route('roles.index')

->with('success','Role created successfully');

}

/**

* Display the specified resource.

*

* @param int $id

* @return \Illuminate\Http\Response

*/

public function show($id)

{

$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'));

}


/**

* Show the form for editing the specified resource.

*

* @param int $id

* @return \Illuminate\Http\Response

*/

public function edit($id)

{

$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'));

}


/**

* Update the specified resource in storage.

*

* @param \Illuminate\Http\Request $request

* @param int $id

* @return \Illuminate\Http\Response

*/

public function update(Request $request, $id)

{

$this->validate($request, [

'name' => 'required',

'permission' => 'required',

]);


$role = Role::find($id);

$role->name = $request->input('name');

$role->save();


$role->syncPermissions($request->input('permission'));


return redirect()->route('roles.index')

->with('success','Role updated successfully');

}

/**

* Remove the specified resource from storage.

*

* @param int $id

* @return \Illuminate\Http\Response

*/

public function destroy($id)

{

DB::table("roles")->where('id',$id)->delete();

return redirect()->route('roles.index')

->with('success','Role deleted successfully');

}

}

Step 10: Add Blade Files

This is last step we have to add numbers view for layouts, users module, roles module, products modules and errors page, so create number of view like as bellow:

resources/views/layouts/app.blade.php

<html lang="{{ app()->getLocale() }}">

<head>

<meta charset="utf-8">

<meta http-equiv="X-UA-Compatible" content="IE=edge">

<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>

<!-- Scripts -->

<script src="{{ asset('js/app.js') }}" defer></script>

<!-- Fonts -->

<link rel="dns-prefetch" href="https://fonts.gstatic.com">

<link href="https://fonts.googleapis.com/css?family=Raleway:300,400,600" rel="stylesheet" type="text/css">

<!-- Styles -->

<link href="{{ asset('css/app.css') }}" rel="stylesheet">

</head>

<body>

<div id="app">

<nav class="navbar navbar-expand-md navbar-light navbar-laravel">

<div class="container">

<a class="navbar-brand" href="{{ url('/') }}">

{{ config('app.name', 'Laravel') }}

</a>

<button class="navbar-toggler" type="button" data-toggle="collapse" data-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 mr-auto"></ul>


<!-- Right Side Of Navbar -->

<ul class="navbar-nav ml-auto">

<!-- Authentication Links -->

@guest

<li><a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a></li>

<li><a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a></li>

@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-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>

{{ Auth::user()->name }} <span class="caret"></span>

</a>


<div class="dropdown-menu" 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" style="display: none;">

@csrf

</form>

</div>

</li>

@endguest

</ul>

</div>

</div>

</nav>


<main class="py-4">

<div class="container">

@yield('content')

</div>

</main>

</div>

</body>

</html>

resources/views/users/index.blade.php

@extends('layouts.app')


@section('content')

<div class="row">

<div class="col-lg-12 margin-tb">

<div class="pull-left">

<h2>Users Management</h2>

</div>

<div class="pull-right">

<a class="btn btn-success" href="{{ route('users.create') }}"> Create New User</a>

</div>

</div>

</div>


@if ($message = Session::get('success'))

<div class="alert alert-success">

<p>{{ $message }}</p>

</div>

@endif


<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 badge-success">{{ $v }}</label>

@endforeach

@endif

</td>

<td>

<a class="btn btn-info" href="{{ route('users.show',$user->id) }}">Show</a>

<a class="btn btn-primary" href="{{ route('users.edit',$user->id) }}">Edit</a>

{!! Form::open(['method' => 'DELETE','route' => ['users.destroy', $user->id],'style'=>'display:inline']) !!}

{!! Form::submit('Delete', ['class' => 'btn btn-danger']) !!}

{!! Form::close() !!}

</td>

</tr>

@endforeach

</table>


{!! $data->render() !!}


@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" href="{{ route('users.index') }}"> 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::open(array('route' => 'users.store','method'=>'POST')) !!}

<div class="row">

<div class="col-xs-12 col-sm-12 col-md-12">

<div class="form-group">

<strong>Name:</strong>

{!! Form::text('name', null, array('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>

{!! Form::text('email', null, array('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>

{!! Form::password('password', array('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>

{!! Form::password('confirm-password', array('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>

{!! Form::select('roles[]', $roles,[], array('class' => 'form-control','multiple')) !!}

</div>

</div>

<div class="col-xs-12 col-sm-12 col-md-12 text-center">

<button type="submit" class="btn btn-primary">Submit</button>

</div>

</div>

{!! Form::close() !!}


@endsection

resources/views/users/edit.blade.php

@extends('layouts.app')


@section('content')

<div class="row">

<div class="col-lg-12 margin-tb">

<div class="pull-left">

<h2>Edit New User</h2>

</div>

<div class="pull-right">

<a class="btn btn-primary" href="{{ route('users.index') }}"> 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::model($user, ['method' => 'PATCH','route' => ['users.update', $user->id]]) !!}

<div class="row">

<div class="col-xs-12 col-sm-12 col-md-12">

<div class="form-group">

<strong>Name:</strong>

{!! Form::text('name', null, array('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>

{!! Form::text('email', null, array('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>

{!! Form::password('password', array('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>

{!! Form::password('confirm-password', array('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>

{!! Form::select('roles[]', $roles,$userRole, array('class' => 'form-control','multiple')) !!}

</div>

</div>

<div class="col-xs-12 col-sm-12 col-md-12 text-center">

<button type="submit" class="btn btn-primary">Submit</button>

</div>

</div>

{!! Form::close() !!}


@endsection

resources/views/users/show.blade.php

@extends('layouts.app')


@section('content')

<div class="row">

<div class="col-lg-12 margin-tb">

<div class="pull-left">

<h2> Show User</h2>

</div>

<div class="pull-right">

<a class="btn btn-primary" href="{{ route('users.index') }}"> Back</a>

</div>

</div>

</div>


<div class="row">

<div class="col-xs-12 col-sm-12 col-md-12">

<div class="form-group">

<strong>Name:</strong>

{{ $user->name }}

</div>

</div>

<div class="col-xs-12 col-sm-12 col-md-12">

<div class="form-group">

<strong>Email:</strong>

{{ $user->email }}

</div>

</div>

<div class="col-xs-12 col-sm-12 col-md-12">

<div class="form-group">

<strong>Roles:</strong>

@if(!empty($user->getRoleNames()))

@foreach($user->getRoleNames() as $v)

<label class="badge badge-success">{{ $v }}</label>

@endforeach

@endif

</div>

</div>

</div>

@endsection

resources/views/roles/index.blade.php

@extends('layouts.app')


@section('content')

<div class="row">

<div class="col-lg-12 margin-tb">

<div class="pull-left">

<h2>Role Management</h2>

</div>

<div class="pull-right">

@can('role-create')

<a class="btn btn-success" href="{{ route('roles.create') }}"> Create New Role</a>

@endcan

</div>

</div>

</div>


@if ($message = Session::get('success'))

<div class="alert alert-success">

<p>{{ $message }}</p>

</div>

@endif


<table class="table table-bordered">

<tr>

<th>No</th>

<th>Name</th>

<th width="280px">Action</th>

</tr>

@foreach ($roles as $key => $role)

<tr>

<td>{{ ++$i }}</td>

<td>{{ $role->name }}</td>

<td>

<a class="btn btn-info" href="{{ route('roles.show',$role->id) }}">Show</a>

@can('role-edit')

<a class="btn btn-primary" href="{{ route('roles.edit',$role->id) }}">Edit</a>

@endcan

@can('role-delete')

{!! Form::open(['method' => 'DELETE','route' => ['roles.destroy', $role->id],'style'=>'display:inline']) !!}

{!! Form::submit('Delete', ['class' => 'btn btn-danger']) !!}

{!! Form::close() !!}

@endcan

</td>

</tr>

@endforeach

</table>


{!! $roles->render() !!}


@endsection

resources/views/roles/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 Role</h2>

</div>

<div class="pull-right">

<a class="btn btn-primary" href="{{ route('roles.index') }}"> 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::open(array('route' => 'roles.store','method'=>'POST')) !!}

<div class="row">

<div class="col-xs-12 col-sm-12 col-md-12">

<div class="form-group">

<strong>Name:</strong>

{!! Form::text('name', null, array('placeholder' => 'Name','class' => 'form-control')) !!}

</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>{{ Form::checkbox('permission[]', $value->id, false, array('class' => 'name')) }}

{{ $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">Submit</button>

</div>

</div>

{!! Form::close() !!}


@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" href="{{ route('roles.index') }}"> 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::model($role, ['method' => 'PATCH','route' => ['roles.update', $role->id]]) !!}

<div class="row">

<div class="col-xs-12 col-sm-12 col-md-12">

<div class="form-group">

<strong>Name:</strong>

{!! Form::text('name', null, array('placeholder' => 'Name','class' => 'form-control')) !!}

</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>{{ Form::checkbox('permission[]', $value->id, in_array($value->id, $rolePermissions) ? true : false, array('class' => 'name')) }}

{{ $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">Submit</button>

</div>

</div>

{!! Form::close() !!}


@endsection

resources/views/roles/show.blade.php

@extends('layouts.app')


@section('content')

<div class="row">

<div class="col-lg-12 margin-tb">

<div class="pull-left">

<h2> Show Role</h2>

</div>

<div class="pull-right">

<a class="btn btn-primary" href="{{ route('roles.index') }}"> Back</a>

</div>

</div>

</div>


<div class="row">

<div class="col-xs-12 col-sm-12 col-md-12">

<div class="form-group">

<strong>Name:</strong>

{{ $role->name }}

</div>

</div>

<div class="col-xs-12 col-sm-12 col-md-12">

<div class="form-group">

<strong>Permissions:</strong>

@if(!empty($rolePermissions))

@foreach($rolePermissions as $v)

<label class="label label-success">{{ $v->name }},</label>

@endforeach

@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">

<div class="pull-left">

<h2>Products</h2>

</div>

<div class="pull-right">

@can('product-create')

<a class="btn btn-success" href="{{ route('products.create') }}"> Create New Product</a>

@endcan

</div>

</div>

</div>


@if ($message = Session::get('success'))

<div class="alert alert-success">

<p>{{ $message }}</p>

</div>

@endif


<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" href="{{ route('products.show',$product->id) }}">Show</a>

@can('product-edit')

<a class="btn btn-primary" href="{{ route('products.edit',$product->id) }}">Edit</a>

@endcan


@csrf

@method('DELETE')

@can('product-delete')

<button type="submit" class="btn btn-danger">Delete</button>

@endcan

</form>

</td>

</tr>

@endforeach

</table>


{!! $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" href="{{ route('products.index') }}"> 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">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" href="{{ route('products.index') }}"> 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">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">

<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 11: Handle Exertion Error

Now, in this step we will handle exertion. if you don't have a permission and try to access that page using browser url then you can give message as like bellow:

add/Exceptions/Handler.php

......

public function render($request, Exception $exception)

{

if ($exception instanceof \Spatie\Permission\Exceptions\UnauthorizedException) {

return response()->json(['User have not permission for this page access.']);

}

return parent::render($request, $exception);

}

....

Now we are ready to to run full example of ACL. so let's run our example so run bellow command for quick run:

php artisan serve

Access By

http://localhost:8000/

I hope it can help you....

Shares