In this tutorial we’ll create a Laravel 9 app using Breeze and then we’ll incorporate Spatie Permission for managing roles and permissions.
Laravel 9.x requires a minimum PHP version of 8.0. This tutorial assumes that you are using Linux, MacOS or WSL on Windows and Node.js, Composer and PHP 8 along with required modules i.e bcmatch, sqlite, mbstring, xml, zip, gd, mcrypt are properly installed. Also make sure that SQLite is installed as we’ll be using SQLite to keep things simple and quick; you may use MySQL or PostgreSQL as you like, however make sure the corresponding PHP module is installed too.
Using Composer, enter following command in terminal to install Laravel 9;
composer create-project laravel/laravel app 9.*
Now go inside newly created app directory by executing;
cd app
Using Composer, add Breeze package for basic authentication implementation;
composer require laravel/breeze:* --dev
Now install Breeze package by executing;
php artisan breeze:install
The above command will also install node.js modules and compile assets (JS and CSS files) for the first time. Next time when there are changes in views, you need to execute npm run build manually.
Next, setup database and Laravel environment file. Here, I’m configuring SQLite database for simplicity purposes.
Being in parent directory (app), execute following command in order to create new SQLite database file;
touch database/database.sqlite
Then find .env config file in the parent directory, open it and amend DB_CONNECTION line as follows;
DB_CONNECTION = sqlite
You can remove DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, DB_PASSWORD from .env when using SQLite database.
Now come steps to setup Spatie Permission in Laravel 9 app. Enter following command to install Spatie Permission package:
composer require spatie/laravel-permission
Locate and open config/app.php file and put Spatie Permission class inside providers array as follows:
'providers' =>
[
// ...
Spatie\Permission\PermissionServiceProvider::class,
];
The above is optional step. Now run the following command to export required files from vendor folder:
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
Amend the database by executing migration command as follows:
php artisan migrate
Finally, add Spatie\Permission\Traits\HasRoles
trait to your User model by modifying app/Models/User.php file as follows:
// ...
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable {
use HasRoles;
// ...
}
All set; now you can start using Spatie Permission for managing roles and permissions. So, let’s use it in our app.
First, create a new file database/seeders/PermissionsDemoSeeder.php by executing following command being in parent directory (app):
touch database/seeders/PermissionsDemoSeeder.php
Then copy the following code inside this seeder file (copied from official documentation);
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use Spatie\Permission\PermissionRegistrar;
class PermissionsDemoSeeder extends Seeder
{
/**
* Create the initial roles and permissions.
*/
public function run()
{
// Reset cached roles and permissions
app()[PermissionRegistrar::class]->forgetCachedPermissions();
// create permissions
Permission::create(['name' => 'edit articles']);
Permission::create(['name' => 'delete articles']);
Permission::create(['name' => 'publish articles']);
Permission::create(['name' => 'unpublish articles']);
// create roles and assign existing permissions
$role1 = Role::create(['name' => 'writer']);
$role1->givePermissionTo('edit articles');
$role1->givePermissionTo('delete articles');
$role2 = Role::create(['name' => 'admin']);
$role2->givePermissionTo('publish articles');
$role2->givePermissionTo('unpublish articles');
// create demo users
$user = \App\Models\User::factory()->create([
'name' => 'Example User',
'email' => 'test@example.com',
]);
$user->assignRole($role1);
$user = \App\Models\User::factory()->create([
'name' => 'Example Admin User',
'email' => 'admin@example.com',
]);
$user->assignRole($role2);
}
}
Now populate / seed the database by entering following command;
php artisan db:seed PermissionsDemoSeeder
The above seeder file will create 4 permissions, 2 roles and 2 users and assign the permissions to respective roles and then assign roles to respective users. Let’s check these permissions. So, create a UserController by entering the following command:
php artisan make:controller UserController
The above command will create app/Http/Controllers/UserController.php file. Now put the following code inside this newly generated UserController.php;
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
class UserController extends Controller
{
public function index()
{
$users = User::all();
return view('users.index', compact('users'));
}
}
Then, edit routes/web.php by importing UserController at the upper side and then inserting a route as follows:
// ...
use App\Http\Controllers\UserController;
// ...
Route::get('users', [UserController::class, 'index'])
->name('users')
->middleware('auth');
Create directory named users inside resources/views directory. If you are in parent directory (app), you may execute following command to make this directory;
mkdir resources/views/users
Now create a file named index.blade.php inside resources/views/users directory. You can execute following command inside parent directory (app) in order to create this file;
touch resources/views/users/index.blade.php
Insert following code inside index.blade.php;
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Users') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
<div class="p-2 mb-2 bg-gray-600 text-white font-bold rounded-md inline-block">
@if(auth()->user()->can('publish articles'))
I can publish articles!
@else
Well, I can't publish articles...
@endif
</div>
<table class="shadow-lg">
<thead>
<tr class="bg-gray-400 text-white font-extrabold" >
<td class="px-4 py-1 text-center" >ID</td>
<td class="px-4 py-1">Name</td>
<td class="px-4 py-1">Email</td>
<td class="px-4 py-1">Can edit articles?</td>
</tr>
</thead>
<tbody>
@foreach($users as $user)
<tr>
<td class="border px-4 py-1 text-center">{{ $user->id }}</td>
<td class="border px-4 py-1">{{ $user->name }}</td>
<td class="border px-4 py-1">{{ $user->email }}</td>
<td class="border px-4 py-1 text-center">
@if($user->can('edit articles'))
Yes
@else
No
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</x-app-layout>
Now execute following command in parent directory to compile UI assets:
npm run build
Finally, execute following command in parent directory to run PHP development server;
php artisan serve
Open browser and enter following URL in address bar;
http://localhost:8000
Now login with test@example.com id as created with above seeder (the default password for above created users is ‘password’) and then enter the following URL:
http://localhost:8000/users
Logoff, then login with admin@example.com id, visit http://localhost:8000/users and observe the permissions’ effect.