Easy roles and permissions in Laravel 5

Laravel comes with Authentication and Authorization out of the box, I have implemented many role and permissions based system in the past, using laravel, it’s peace of cake. In this post, we are going to implement a fully working and extensible roles and permissions on laravel 5. When we finish we will have a starter kit which we can use for our any future project which needs roles and permissions based access control (ACL).

Laravel Permissions

Although laravel comes with Policies to handle the authorization I wanted to have an option to just create permissions in the database which we can manage by a UI in the admin panel, pretty standard. we can implement our own role and permission from scratch but I am going to use spatie/laravel-permission package for this. This package was inspired by Jeffrey ways screencast and it’s very well maintained and very easy to use. It has everything we need and plays very well with Laravel Gate and Policies implementations.

laravel-role-permissions-dashboard

Source Code Laravel 5.4
Source Code Laravel 5.7

Scaffold app

Let’s get started by creating a fresh laravel app by running laravel new rpl or if you don’t have laravel command line tool, you can use composer to get it composer create-project --prefer-dist laravel/laravel rpl. rpl is the name of app which is an abbreviation for Role Permissions Laravel.

Once the installation is done, make necessary changes in .env so you can connect to a database.

Setup packages

We will use laravel authorization which comes bundled, let’s scaffold it using auth:make command. It will create a fully functional login, register and password reset features. Now that’s done, let’s pull packages we will need in this app.

Edit your composer.json to add below dependencies.

"require": {
        ...
        "spatie/laravel-permission": "^2.1",
        "laracasts/flash": "^3.0",
        "laravelcollective/html": "^5.3.0"
    },

Apart from permissions package, I have also grabbed flash to show notification alerts and laravelcollective html to create forms with the option to model bind them.

Now Add them in ServiceProvider and in aliases array, open config/app.php

'providers' => [
    ...
    Spatie\Permission\PermissionServiceProvider::class,        
    Laracasts\Flash\FlashServiceProvider::class,        
    Collective\Html\HtmlServiceProvider::class,
    ...
],

'aliases' => [
    ...
    'Form' => Collective\Html\FormFacade::class,
    'Html' => Collective\Html\HtmlFacade::class,
]

Cool, now let’s start by publishing migration which comes from permissions package, which will create tables for roles and permissions.

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

Great, now we need to create our Resource, I am going to create Post, Role, Permission models with resource controller. User model is already present so we will use it.

// Create Post model with migration and resource controller
php artisan make:model Post -m -c --resource

// Create Role model and resource controller
php artisan make:model Role -c --resource

// Create Permission model and resource controller
php artisan make:model Permission -c --resource

Spatie\Permission already have role and permissions model, we will just extend them in order to do any changes if needed in future.

// Permission Model
class Permission extends \Spatie\Permission\Models\Permission { }

// Role Model
class Role extends \Spatie\Permission\Models\Role { }

We need to add HasRoles trait provided by the package to give the user all the power of laravel permissions.

use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    use HasRoles;
    ...

Now we have all the boilerplate out of the way, let’s create simple database seeder so we can build and test our app, you can read more about advance database seeding in this post, open database/seeds/DatabaseSeeder.php and add this code.

public function run()
    {
        // Ask for db migration refresh, default is no
        if ($this->command->confirm('Do you wish to refresh migration before seeding, it will clear all old data ?')) {
            // Call the php artisan migrate:refresh
            $this->command->call('migrate:refresh');
            $this->command->warn("Data cleared, starting from blank database.");
        }

        // Seed the default permissions
        $permissions = Permission::defaultPermissions();

        foreach ($permissions as $perms) {
            Permission::firstOrCreate(['name' => $perms]);
        }

        $this->command->info('Default Permissions added.');

        // Confirm roles needed
        if ($this->command->confirm('Create Roles for user, default is admin and user? [y|N]', true)) {

            // Ask for roles from input
            $input_roles = $this->command->ask('Enter roles in comma separate format.', 'Admin,User');

            // Explode roles
            $roles_array = explode(',', $input_roles);

            // add roles
            foreach($roles_array as $role) {
                $role = Role::firstOrCreate(['name' => trim($role)]);

                if( $role->name == 'Admin' ) {
                    // assign all permissions
                    $role->syncPermissions(Permission::all());
                    $this->command->info('Admin granted all the permissions');
                } else {
                    // for others by default only read access
                    $role->syncPermissions(Permission::where('name', 'LIKE', 'view_%')->get());
                }

                // create one user for each role
                $this->createUser($role);
            }

            $this->command->info('Roles ' . $input_roles . ' added successfully');

        } else {
            Role::firstOrCreate(['name' => 'User']);
            $this->command->info('Added only default user role.');
        }

        // now lets seed some posts for demo
        factory(\App\Post::class, 30)->create();
        $this->command->info('Some Posts data seeded.');
        $this->command->warn('All done :)');
    }

    /**
     * Create a user with given role
     *
     * @param $role
     */
    private function createUser($role)
    {
        $user = factory(User::class)->create();
        $user->assignRole($role->name);

        if( $role->name == 'Admin' ) {
            $this->command->info('Here is your admin details to login:');
            $this->command->warn($user->email);
            $this->command->warn('Password is "secret"');
        }
    }

Now add defaultPermissions in Permissions Model which we have created.

public static function defaultPermissions()
{
    return [
        'view_users',
        'add_users',
        'edit_users',
        'delete_users',

        'view_roles',
        'add_roles',
        'edit_roles',
        'delete_roles',

        'view_posts',
        'add_posts',
        'edit_posts',
        'delete_posts',
    ];
}

Post model factory contains only 2 fileds, title and body. You should setup the migration and factory. Now run the seeder using php artisan db:seed it should give an admin user which you can use to login.

Now you can login with admin user but there is no access control in place, I will create the User Resource first.

Create the UserController and add below code.

public function index()
{
    $result = User::latest()->paginate();
    return view('user.index', compact('result'));
}

public function create()
{
    $roles = Role::pluck('name', 'id');
    return view('user.new', compact('roles'));
}

public function store(Request $request)
{
    $this->validate($request, [
        'name' => 'bail|required|min:2',
        'email' => 'required|email|unique:users',
        'password' => 'required|min:6',
        'roles' => 'required|min:1'
    ]);

    // hash password
    $request->merge(['password' => bcrypt($request->get('password'))]);

    // Create the user
    if ( $user = User::create($request->except('roles', 'permissions')) ) {
        $this->syncPermissions($request, $user);
        flash('User has been created.');
    } else {
        flash()->error('Unable to create user.');
    }

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

public function edit($id)
{
    $user = User::find($id);
    $roles = Role::pluck('name', 'id');
    $permissions = Permission::all('name', 'id');

    return view('user.edit', compact('user', 'roles', 'permissions'));
}

public function update(Request $request, $id)
{
    $this->validate($request, [
        'name' => 'bail|required|min:2',
        'email' => 'required|email|unique:users,email,' . $id,
        'roles' => 'required|min:1'
    ]);

    // Get the user
    $user = User::findOrFail($id);

    // Update user
    $user->fill($request->except('roles', 'permissions', 'password'));

    // check for password change
    if($request->get('password')) {
        $user->password = bcrypt($request->get('password'));
    }

    // Handle the user roles
    $this->syncPermissions($request, $user);

    $user->save();
    flash()->success('User has been updated.');
    return redirect()->route('users.index');
}

public function destroy($id)
{
    if ( Auth::user()->id == $id ) {
        flash()->warning('Deletion of currently logged in user is not allowed :(')->important();
        return redirect()->back();
    }

    if( User::findOrFail($id)->delete() ) {
        flash()->success('User has been deleted');
    } else {
        flash()->success('User not deleted');
    }

    return redirect()->back();
}

private function syncPermissions(Request $request, $user)
{
    // Get the submitted roles
    $roles = $request->get('roles', []);
    $permissions = $request->get('permissions', []);

    // Get the roles
    $roles = Role::find($roles);

    // check for current role changes
    if( ! $user->hasAllRoles( $roles ) ) {
        // reset all direct permissions for user
        $user->permissions()->sync([]);
    } else {
        // handle permissions
        $user->syncPermissions($permissions);
    }

    $user->syncRoles($roles);
    return $user;
}

Everything is commented and self-explanatory, it’s a simple controller to perform CRUD operation with user level permission override so you can give access to certain permissions for the specific user. Now register the route for all the resource controllers.

Route::group( ['middleware' => ['auth']], function() {
    Route::resource('users', 'UserController');
    Route::resource('roles', 'RoleController');
    Route::resource('posts', 'PostController');
});

Go ahead and create the PostController by yourself, you can always access the source code if need help.

Authorization

This is the main part, authorization will be in 2 level, first is at the controller level and second in view level. In view, if you don’t have permission to add_users then it doesn’t make sense to show Create button. this can be done using @can('add_users') directive in blade template.

admin-role-users-view

...
@can('add_users')
    <a href="{{ route('users.create') }}" class="btn btn-primary btn-sm">
        <i class="glyphicon glyphicon-plus-sign"></i> Create
    </a>
@endcan
...

Similarly, if you don’t have access to edit_users you should not see the edit button or delete button in the table.

user-role-users-view

<table class="table table-bordered table-striped table-hover" id="data-table">
    <thead>
    <tr>
        ....
        <th>Created At</th>
        @can('edit_users', 'delete_users')
            <th class="text-center">Actions</th>
        @endcan
    </tr>
    </thead>
    <tbody>
    @foreach($result as $item)
        <tr>
            ...
            @can('edit_users')
            <td class="text-center">
                // action buttons
            </td>
            @endcan
        </tr>
    @endforeach
    </tbody>
</table>

Now that’s fine, but some malicious user can still directly visit the URL and he will be able to access the protected route. To prevent that we need protection on controller@method level.

Authorizable Trait

We can add $user->can() check in every method to handle authorization but it will make it more difficult to maintain and since we will be using this in multiple resource controller it will be good to extract out this logic in a trait which will handle the authorization automatically, sounds good! let’s do it.

namespace App;

trait Authorizable
{
    private $abilities = [
        'index' => 'view',
        'edit' => 'edit',
        'show' => 'view',
        'update' => 'edit',
        'create' => 'add',
        'store' => 'add',
        'destroy' => 'delete'
    ];

    /**
     * Override of callAction to perform the authorization before
     *
     * @param $method
     * @param $parameters
     * @return mixed
     */
    public function callAction($method, $parameters)
    {
        if( $ability = $this->getAbility($method) ) {
            $this->authorize($ability);
        }

        return parent::callAction($method, $parameters);
    }

    public function getAbility($method)
    {
        $routeName = explode('.', \Request::route()->getName());
        $action = array_get($this->getAbilities(), $method);

        return $action ? $action . '_' . $routeName[0] : null;
    }

    private function getAbilities()
    {
        return $this->abilities;
    }

    public function setAbilities($abilities)
    {
        $this->abilities = $abilities;
    }
}

In this trait we have to override the callAction method which gets called by the router to trigger respective method on the resource controller, that’s good place to check the permission, so we get the route name in users case it will be users.index, users.store, users.update etc.. we have mapped the abilities to our resource controller route naming conventions.

what happens is when a user visits route named users.index, it gets translated into view_users ability to check against in authorize($ability) method by getAbility() method, when user visits edit page route users.edit it will be translated as edit_users and so on. by extracting this logic in a Trait we will be able to apply authorization on any resource controller we wanted.

Add our trait on UserController.

use App\Authorizable;

class UserController extends Controller
{
    use Authorizable;
    ...

That’s it, your controller is protected, the only user who has permissions to visit certain route can access it.

When user doesn’t have permission they get AuthorizationException exception, which is not very friendly to end user, let’s handle this in global Handler so we can display a notification and send the user back to dashboard if the try to visit some route which they don’t suppose to access.

AuthorizationException Exception Handler

Open the app/Exceptions/Handler.php and add this in render method

public function render($request, Exception $exception)
{
    if ($exception instanceof AuthorizationException) {
        return $this->unauthorized($request, $exception);
    }

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

private function unauthorized($request, Exception $exception)
{
    if ($request->expectsJson()) {
        return response()->json(['error' => $exception->getMessage()], 403);
    }

    flash()->warning($exception->getMessage());
    return redirect()->route('home');
}

This will redirect back to home route with flash notification if user doesn’t have access to the action.

Role Management

Let’s create the roles management resource controller. which admin can use to create the new role and give or change permission to them.

class RoleController extends Controller
{
    use Authorizable;

    public function index()
    {
        $roles = Role::all();
        $permissions = Permission::all();

        return view('role.index', compact('roles', 'permissions'));
    }

    public function store(Request $request)
    {
        $this->validate($request, ['name' => 'required|unique:roles']);

        if( Role::create($request->only('name')) ) {
            flash('Role Added');
        }

        return redirect()->back();
    }

    public function update(Request $request, $id)
    {
        if($role = Role::findOrFail($id)) {
            // admin role has everything
            if($role->name === 'Admin') {
                $role->syncPermissions(Permission::all());
                return redirect()->route('roles.index');
            }

            $permissions = $request->get('permissions', []);
            $role->syncPermissions($permissions);
            flash( $role->name . ' permissions has been updated.');
        } else {
            flash()->error( 'Role with id '. $id .' note found.');
        }

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

Now lets add the views for role, create resources/views/role/index.blade.php with below markup.

@extends('layouts.app')

@section('title', 'Roles & Permissions')

@section('content')
    <!-- Modal -->
    <div class="modal fade" id="roleModal" tabindex="-1" role="dialog" aria-labelledby="roleModalLabel">
        <div class="modal-dialog" role="document">
            {!! Form::open(['method' => 'post']) !!}

            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
                    <h4 class="modal-title" id="roleModalLabel">Role</h4>
                </div>
                <div class="modal-body">
                    <!-- name Form Input -->
                    <div class="form-group @if ($errors->has('name')) has-error @endif">
                        {!! Form::label('name', 'Name') !!}
                        {!! Form::text('name', null, ['class' => 'form-control', 'placeholder' => 'Role Name']) !!}
                        @if ($errors->has('name')) <p class="help-block">{{ $errors->first('name') }}</p> @endif
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>

                    <!-- Submit Form Button -->
                    {!! Form::submit('Submit', ['class' => 'btn btn-primary']) !!}
                </div>
                {!! Form::close() !!}
            </div>
        </div>
    </div>

    <div class="row">
        <div class="col-md-5">
            <h3>Roles</h3>
        </div>
        <div class="col-md-7 page-action text-right">
            @can('add_roles')
                <a href="#" class="btn btn-sm btn-success pull-right" data-toggle="modal" data-target="#roleModal"> <i class="glyphicon glyphicon-plus"></i> New</a>
            @endcan
        </div>
    </div>


    @forelse ($roles as $role)
        {!! Form::model($role, ['method' => 'PUT', 'route' => ['roles.update',  $role->id ], 'class' => 'm-b']) !!}

        @if($role->name === 'Admin')
            @include('shared._permissions', [
                          'title' => $role->name .' Permissions',
                          'options' => ['disabled'] ])
        @else
            @include('shared._permissions', [
                          'title' => $role->name .' Permissions',
                          'model' => $role ])
            @can('edit_roles')
                {!! Form::submit('Save', ['class' => 'btn btn-primary']) !!}
            @endcan
        @endif

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

    @empty
        <p>No Roles defined, please run <code>php artisan db:seed</code> to seed some dummy data.</p>
    @endforelse
@endsection

Let’s add resources/views/shared/_permissions.blade.php template.

<div class="panel panel-default">
    <div class="panel-heading" role="tab" id="{{ isset($title) ? str_slug($title) :  'permissionHeading' }}">
        <h4 class="panel-title">
            <a role="button" data-toggle="collapse" data-parent="#accordion" href="#dd-{{ isset($title) ? str_slug($title) :  'permissionHeading' }}" aria-expanded="{{ $closed or 'true' }}" aria-controls="dd-{{ isset($title) ? str_slug($title) :  'permissionHeading' }}">
                {{ $title or 'Override Permissions' }} {!! isset($user) ? '<span class="text-danger">(' . $user->getDirectPermissions()->count() . ')</span>' : '' !!}
            </a>
        </h4>
    </div>
    <div id="dd-{{ isset($title) ? str_slug($title) :  'permissionHeading' }}" class="panel-collapse collapse {{ $closed or 'in' }}" role="tabpanel" aria-labelledby="dd-{{ isset($title) ? str_slug($title) :  'permissionHeading' }}">
        <div class="panel-body">
            <div class="row">
                @foreach($permissions as $perm)
                    <?php
                        $per_found = null;

                        if( isset($role) ) {
                            $per_found = $role->hasPermissionTo($perm->name);
                        }

                        if( isset($user)) {
                            $per_found = $user->hasDirectPermission($perm->name);
                        }
                    ?>

                    <div class="col-md-3">
                        <div class="checkbox">
                            <label class="{{ str_contains($perm->name, 'delete') ? 'text-danger' : '' }}">
                                {!! Form::checkbox("permissions[]", $perm->name, $per_found, isset($options) ? $options : []) !!} {{ $perm->name }}
                            </label>
                        </div>
                    </div>
                @endforeach
            </div>
        </div>
    </div>
</div>

If you visit now /roles you can find will be able to manage the roles and permission.

roles-and-permissions

Permissions Management

Permissions are not going to be changed very often in most cases, you can just add them directly into the database. I am leaving the implementation for this. It’s simple CRUD, if you wanted you can implement it. One thing we can do to create a command which we can run to create permissions, something like php artisan auth:permission tasks, which will create 'view_tasks', 'add_tasks', 'edit_tasks', 'delete_tasks' the permissions for tasks model, and if we pass --remove it will delete permissions on it.

Create our command by running php artisan make:command AuthPermissionCommand.

class AuthPermissionCommand extends Command
{
    protected $signature = 'auth:permission {name} {--R|remove}';
    ...

    public function handle()
    {
        $permissions = $this->generatePermissions();

        // check if its remove
        if( $is_remove = $this->option('remove') ) {
            // remove permission
            if( Permission::where('name', 'LIKE', '%'. $this->getNameArgument())->delete() ) {
                $this->warn('Permissions ' . implode(', ', $permissions) . ' deleted.');
            }  else {
                $this->warn('No permissions for ' . $this->getNameArgument() .' found!');
            }

        } else {
            // create permissions
            foreach ($permissions as $permission) {
                Permission::firstOrCreate(['name' => $permission ]);
            }

            $this->info('Permissions ' . implode(', ', $permissions) . ' created.');
        }

        // sync role for admin
        if( $role = Role::where('name', 'Admin')->first() ) {
            $role->syncPermissions(Permission::all());
            $this->info('Admin permissions');
        }
    }

    private function generatePermissions()
    {
        $abilities = ['view', 'add', 'edit', 'delete'];
        $name = $this->getNameArgument();

        return array_map(function($val) use ($name) {
            return $val . '_'. $name;
        }, $abilities);
    }
    
    private function getNameArgument()
    {
        return strtolower(str_plural($this->argument('name')));
    }
}

Our command is ready, next let’s register it in Kernel, open the app/Console/Kernel.php and add.

App\Console\Commands\AuthPermissionCommand;

class Kernel extends ConsoleKernel
{
    protected $commands = [
        AuthPermissionCommand::class
    ];
    ...

The auth:permission command is ready, now you can run it to add/remove permissions.

If you added permissions manually in the db, don’t forget to run php artisan cache:forget spatie.permission.cache, otherwise new permissions wont work.

Finally, we have a starter kit which you can use for any new project required roles and permissions. Check the source code & I hope you found it useful, let me know in the comments if you have any question.

Source Code Laravel 5.4
Source Code Laravel 5.7

141 Responses to “Easy roles and permissions in Laravel 5”

  1. bambamboole

    I added one custom permission directly to the database (not crud permission) and the template breaks. Do you have any solution for this?

    • Saqueib

      You can always fallback to @can('your_custom_permissions') in blade template. same is true for controller Auth::user()->can('your_custom_permissions') or you can use authorized like this


      $this->authorize('your_custom_permissions');

      I would suggest pick a naming convention for route and permission and stick to it, you can also match the $abilities array in Authorizable traits line number 15 for your specific need.

      If you need any further help, please share your custom route and some permissions you wanted to add. by default a permission name is made of {controller_method}_{route_name} see the trait.

      • bambamboole

        I just added a new permission as an example for a custom permission and the route with the role/permissions form broke.
        I know how I can authorize against a custom permission, but i want the custom permission in the permissions view with the other permissions 🙂

        • Mohd Saqueib

          ok, if you can share the permissions you wanted to add, i will try to reproduce it at my end to better understanding.

          I need to add these directly in database right?

          • bambamboole

            I just added a new permission via Sequel Pro called custom_permission. nothing more.
            After adding this permission the permission template breaks…

          • Heya, If I try and add a custom permission called ‘access_staff_panel’ it would break the permissions blade saying . “There is no permission named `access_staff_panel` for guard `web`.” As mentioned I did this just using Sequal Pro, how would I go about adding a custom permission that I can assign to roles + users?

  2. Nice tutorial, thank you! It has helped me get ACL working on my new app. I am experiencing one small issue though: Trying to use the auth:permission artisan command works for creating new permissions, but trying to use the –R or remove option results in “The “–R” option does not exist.” or “Too many arguments, expected arguments “command” “name”. respectively. Any ideas why I can’t specify remove?

    • Saqueib

      hey Chris, you need to user

      php artisan auth:permission Comment -R
      or
      php artisan auth:permission Comment –remove

      to remove permissions.

  3. Satish Reddy

    excellent tutorial, it showed me the way. i struck here, where in migrations when i see migrations it can create model_has_roles and model_has_permissions tables. But when i run the code i am getting errors like ‘base table or view not found. we don’t have tables like user_has_roles and user_has_permissions table. Please suggest. thank you in advance. thank you

    • Saqueib

      Its seems you forgot to ran the migrations, please try running it but

      php artisan migrate
      or
      php artisan migrate:refresh

      or if you have cloned code from repo you can run the php artisan db:seed it will prompt u to refresh the migration.

      Let me know how it goes

  4. madsem

    Hey Saqueib,

    very nice tutorial! Thanks a lot, will use this for my new app.

    Quick question: As far as I can see, there is nothing prepared to make queries in a Controller based on user permissions.

    For example on an edit view, include roles for admins, but not for normal users.

    How would you do that?

    Just rely on @can(‘admin’) in Blade, or actually do two seperate Eloquent queries for each user role to only include the data they are allowed to see?

    • Saqueib

      hi @madsem:disqus you can query or check for permission in controller using $user->can('assign_roles')
      .

      To show the user roles for admin I would create a custom permission and assign it to admin role, and later in blade view i would check it by @can(‘assign_roles’) directive. don’t forget to run php artisan cache:forget spatie.permission.cache to clear the cache.

      • madsem

        got it, thanks 🙂

        I think I wasn’t 100% clear with my question.

        I meant: Would you even make Eloquent queries based on user roles, or just one query for all data a View needs, and then only use @can(‘permission’) in the Blade view to include/exclude data, or would you make multiple DB queries, one for each role? Like what do you think is best practice here 🙂

      • madsem

        Saqueib I believe there are two small errors in the Git repo.
        “`
        UserController.php

        } else {

        // handle permissions

        $user->syncPermissions($permissions);

        }
        “`

        should be:
        “`

        }

        // handle permissions

        $user->syncPermissions($permissions);

        “`

        otherwise permissions are not correctly updated when you override them on a per user basis.

        And in Handler.php you have commented out the render() method, which causes the auth check to throw an error when a user does an unauthorized action.

  5. Jonathan Espinosa

    Great Tutorial, I am new in laravel and I am learning how to manage the roles and permissions situation, Can you help to understand how to add new permissions and roles? and to martch it with the controllers or routes, I can understand that. I hope you can help me. sorry for this noob cuestion.

    • Saqueib

      Thanks, If you clone the repo you can add Roles by running php artisan db:seed. It will ask you to type roles in comma separate format, like ‘Admin,User’ will create these 2 roles. or you can manually add a Role directly in roles mysql table.

      For permissions you can use another command php artisan auth:permission Post, it will create permissions for Post model.

      Now when you have got roles and permissions ready you can add Authorizable trait on a any resource controller to protect it via permissions.


      class PostController extends Controller
      {
      use Authorizable;

      I hope it helps you. If you have any question let me know

    • Saqueib

      It seems something wrong with permissions, directories within the storage and the bootstrap/cache directories should be writable by your web server. Also run composer update on server

      • Morshed Khan Rana

        when I run this project in localhost then work perfectly but when I upload this project host in live server then given this error ,, please tell me how can I fix it !

        (1/1) FatalErrorException
        syntax error, unexpected ‘:’, expecting ‘;’ or ‘{‘
        in PermissionRegistrar.php (line 33)

        http://postest.hello-sylhet.com/
        please reply !!

  6. tahjid ashfaque

    I am total newbie in laravel, I tried following this tutorial, when I run php artisan db:seed, I am getting this error,

    [SymfonyComponentDebugExceptionFatalThrowableError]
    Class ‘Permission’ not found
    but my Permission model is defined , please help.
    Thank You

  7. ADEBOYE OLAITAN MERCY

    Great tutorial, I have everything working until i get ‘This action is authorized’ for a particular route which i have given permission to

    Am i missing something

  8. ADEBOYE OLAITAN MERCY

    When i open route like /patient/{patient},
    Everything is fine
    But when i visit routes like
    /patient/{patient}/update,

    If gives
    ‘This action is authorized’

    Help please

    • Saqueib

      Authorizable trait will work only if you follow the Laravel resource controller, for example route for update should look like this


      PUT|PATCH | /patient/{patient}

      You can always use authorize('edit_patient') in your controller methods if you don’t want to follow resourceful controller schema

  9. RichLove

    Hi. Great tutorial, I’m still working through it but encountered an issue. The check here: if ($exception instanceof AuthorizationException) in Handler.php is returning false when there is an auth error. When I dump $exception it looks like an instance of AuthorizationException so not sure why the check return false. I noticed also this line of code is commented out in the project github repo.

    https://github.com/saqueib/roles-permissions-laravel/blob/master/app/Exceptions/Handler.php#L48

  10. Nabiullah Khan

    Hi Sequeib,
    Thanks for wonderful tutorial, please help me.

    when I use “php artisan migrate” so it gives error

    [IlluminateDatabaseQueryException]

    SQLSTATE[42000]: Syntax error or access violation: 1103 Incorrect table name ” (SQL: create table “ (id int unsigned not null auto_increment primary key, `name`

    varchar(191) not null, `guard_name` varchar(191) not null, `created_at` timestamp null, `updated_at` timestamp null) default character set utf8mb4 collate utf8mb4_un

    icode_ci)

    [PDOException]

    SQLSTATE[42000]: Syntax error or access violation: 1103 Incorrect table name ”

    • Saqueib

      Its seems you are not getting the table name from config file, please publish the vendor config using this.

      php artisan vendor:publish --provider="SpatiePermissionPermissionServiceProvider" --tag="config"

      Let me know how it goes.

  11. somenet77

    I have successfully configure the above example and worked fine for laravel resource controller. But when i have added custom method in the controller the 403 error doesn’t work no protection over such url. But when i have added the such method in Abilities array in Authorizable traits it worked fine. But my question is, it is not good to added every custom method in the Abilities array. So what is the solution.

    • Saqueib

      You don’t need to add in abilities array, that array is used if you want to change naming convention of routes altogether, by default its set for resource controller naming convention.

      For any custom method authorization you should use


      public function customeControllerAction() {

      $this->authorize('your_custom_permission');

      ...
      }

      I hope this helps

      • somenet77

        Thanks now work fine. But still confuse in AuthorizationException Exception Handler when i have added the code above you wrote in Handler.php the permission doesn’t work, every user has access all url although i doesn’t give the permission for those user. What is the problem ?

        • Saqueib

          Its simple, AuthorizationException Handler checks if its an Unauthorized Exception it returns redirect to home with a flash mag, and if its an ajax call it will return unauthorize msg as json. thats all its doing

    • Mohd Saqueib

      You need to give user permissions to access that route, log in as admin and give permission. If you dont want ACL on a certain controller just remove Authorizable trait from controller and access will be allowed by default.

      If you need any other help let me know with some code where you are getting this unauthorized exception.

    • Saqueib

      You need to give user permissions to access that route, log in as admin and give permission. If you dont want ACL on a certain controller just remove Authorizable trait from controller and access will be allowed by default.

      If you need any other help let me know with some code where you are getting this unauthorized exception.

      • Actually i am recovering a old project that use laravel-permission package, now i am able to access the role and user by commenting the Authorizable trait. Even if i login as admin i am not able to make changes in the role and user view.

  12. Hi there, when I run the php artisan db:seed, everything works normal till the:
    “Enter roles in comma separate format. [Admin,User]:”

    when I entered the roles, it show something like this:
    [SymfonyComponentDebugExceptionFatalThrowableError]
    Parse error: syntax error, unexpected ‘;’, expecting function (T_FUNCTION)

    I rechecked the DatabaseSeeder.php and everything look fine, but maybe I miss something

    and btw, nice tutorial, and thank you.

    • Saqueib

      Thanks for sharing code, here is the issue, you have translated the names of routes and they are not updated in view files. Change names in these files.


      # routes/web.php
      Route::resource('usuarios', 'UserController'); // change users to usuarios

      // update the route names in views
      # resources/views/layouts/app.blade.php line:51-57
      @can('ver_usuarios')


      Users

      @endcan

      # resources/views/user/index.blade.php line:12,43
      Create

      @include('shared._actions', [
      'entity' => 'usuarios',
      'id' => $item->id
      ])

      This will show you the users list, but you will be needed to update it everywhere, in Form action and in other views also.

      created a pull request, merge it on github to get the fix.

      I hope it helps, let me know how it goes

  13. Hi, I made extra column for the role table, called role_desc and it already work when I add new role with its description. It also already displayed at the Role page. But, when I try to edit user, it gave an error, undefined variable “role”. So my question is, how to make it work at user edit page?
    for example, “Your Current role is Admin. (Role Description: …).
    At _permissions.blade.php, I used “Role Description: {{ $role->role_desc }}” to show role description.
    Thank you.

  14. Colin Stewart

    Hi,
    Thanks for a great tutorial.
    When I run the command “php artisan db:seed” I get this error:
    [InvalidArgumentException]
    Unable to locate factory with name [default] [AppPost].
    Any idea why?

  15. Ayman Ishimwe

    I have bumped into an issue, after adding other permissions manually, i couldn’t manage to make them also default to the Admin role, and it also seems like i can’t check(tick) them. Can someone help me out!

    Regards!

  16. Hi, Great post. but while i am using
    php artisan vendor:publish –provider=”SpatiePermissionPermissionServiceProvider” –tag=”migrations”

    this command its showing me an exception

    PHP Fatal error: Class ‘SpatiePermissionPermissionServiceProvider’ not found in C:rplvendorlaravelframeworksrcIlluminateFoundationProviderRepository.php on line 208
    [SymfonyComponentDebugExceptionFatalErrorException]
    Class ‘SpatiePermissionPermissionServiceProvider’ not found

    Kindly help me out. Thanks in advance

    • As it says, you need to install add
      SpatiePermissionPermissionServiceProvider::class,
      In config/app.php providers array, currently laravel is not able to find this provider binding

      • Thanks for your time.
        kindly check my code. and help me

        env(‘APP_NAME’, ‘Laravel’),

        /*
        |————————————————————————–
        | Application Environment
        |————————————————————————–
        |
        | This value determines the “environment” your application is currently
        | running in. This may determine how you prefer to configure various
        | services your application utilizes. Set this in your “.env” file.
        |
        */

        ‘env’ => env(‘APP_ENV’, ‘production’),

        /*
        |————————————————————————–
        | Application Debug Mode
        |————————————————————————–
        |
        | When your application is in debug mode, detailed error messages with
        | stack traces will be shown on every error that occurs within your
        | application. If disabled, a simple generic error page is shown.
        |
        */

        ‘debug’ => env(‘APP_DEBUG’, false),

        /*
        |————————————————————————–
        | Application URL
        |————————————————————————–
        |
        | This URL is used by the console to properly generate URLs when using
        | the Artisan command line tool. You should set this to the root of
        | your application so that it is used when running Artisan tasks.
        |
        */

        ‘url’ => env(‘APP_URL’, ‘http://localhost’),

        /*
        |————————————————————————–
        | Application Timezone
        |————————————————————————–
        |
        | Here you may specify the default timezone for your application, which
        | will be used by the PHP date and date-time functions. We have gone
        | ahead and set this to a sensible default for you out of the box.
        |
        */

        ‘timezone’ => ‘UTC’,

        /*
        |————————————————————————–
        | Application Locale Configuration
        |————————————————————————–
        |
        | The application locale determines the default locale that will be used
        | by the translation service provider. You are free to set this value
        | to any of the locales which will be supported by the application.
        |
        */

        ‘locale’ => ‘en’,

        /*
        |————————————————————————–
        | Application Fallback Locale
        |————————————————————————–
        |
        | The fallback locale determines the locale to use when the current one
        | is not available. You may change the value to correspond to any of
        | the language folders that are provided through your application.
        |
        */

        ‘fallback_locale’ => ‘en’,

        /*
        |————————————————————————–
        | Encryption Key
        |————————————————————————–
        |
        | This key is used by the Illuminate encrypter service and should be set
        | to a random, 32 character string, otherwise these encrypted strings
        | will not be safe. Please do this before deploying an application!
        |
        */

        ‘key’ => env(‘APP_KEY’),

        ‘cipher’ => ‘AES-256-CBC’,

        /*
        |————————————————————————–
        | Logging Configuration
        |————————————————————————–
        |
        | Here you may configure the log settings for your application. Out of
        | the box, Laravel uses the Monolog PHP logging library. This gives
        | you a variety of powerful log handlers / formatters to utilize.
        |
        | Available Settings: “single”, “daily”, “syslog”, “errorlog”
        |
        */

        ‘log’ => env(‘APP_LOG’, ‘single’),

        ‘log_level’ => env(‘APP_LOG_LEVEL’, ‘debug’),

        /*
        |————————————————————————–
        | Autoloaded Service Providers
        |————————————————————————–
        |
        | The service providers listed here will be automatically loaded on the
        | request to your application. Feel free to add your own services to
        | this array to grant expanded functionality to your applications.
        |
        */

        ‘providers’ => [

        /*
        * Laravel Framework Service Providers…
        */
        IlluminateAuthAuthServiceProvider::class,
        IlluminateBroadcastingBroadcastServiceProvider::class,
        IlluminateBusBusServiceProvider::class,
        IlluminateCacheCacheServiceProvider::class,
        IlluminateFoundationProvidersConsoleSupportServiceProvider::class,
        IlluminateCookieCookieServiceProvider::class,
        IlluminateDatabaseDatabaseServiceProvider::class,
        IlluminateEncryptionEncryptionServiceProvider::class,
        IlluminateFilesystemFilesystemServiceProvider::class,
        IlluminateFoundationProvidersFoundationServiceProvider::class,
        IlluminateHashingHashServiceProvider::class,
        IlluminateMailMailServiceProvider::class,
        IlluminateNotificationsNotificationServiceProvider::class,
        IlluminatePaginationPaginationServiceProvider::class,
        IlluminatePipelinePipelineServiceProvider::class,
        IlluminateQueueQueueServiceProvider::class,
        IlluminateRedisRedisServiceProvider::class,
        IlluminateAuthPasswordsPasswordResetServiceProvider::class,
        IlluminateSessionSessionServiceProvider::class,
        IlluminateTranslationTranslationServiceProvider::class,
        IlluminateValidationValidationServiceProvider::class,
        IlluminateViewViewServiceProvider::class,
        SpatiePermissionPermissionServiceProvider::class,
        LaracastsFlashFlashServiceProvider::class,
        CollectiveHtmlHtmlServiceProvider::class,

        /*
        * Package Service Providers…
        */
        LaravelTinkerTinkerServiceProvider::class,

        /*
        * Application Service Providers…
        */
        AppProvidersAppServiceProvider::class,
        AppProvidersAuthServiceProvider::class,
        // AppProvidersBroadcastServiceProvider::class,
        AppProvidersEventServiceProvider::class,
        AppProvidersRouteServiceProvider::class,

        ],

        /*
        |————————————————————————–
        | Class Aliases
        |————————————————————————–
        |
        | This array of class aliases will be registered when this application
        | is started. However, feel free to register as many as you wish as
        | the aliases are “lazy” loaded so they don’t hinder performance.
        |
        */

        ‘aliases’ => [

        ‘App’ => IlluminateSupportFacadesApp::class,
        ‘Artisan’ => IlluminateSupportFacadesArtisan::class,
        ‘Auth’ => IlluminateSupportFacadesAuth::class,
        ‘Blade’ => IlluminateSupportFacadesBlade::class,
        ‘Broadcast’ => IlluminateSupportFacadesBroadcast::class,
        ‘Bus’ => IlluminateSupportFacadesBus::class,
        ‘Cache’ => IlluminateSupportFacadesCache::class,
        ‘Config’ => IlluminateSupportFacadesConfig::class,
        ‘Cookie’ => IlluminateSupportFacadesCookie::class,
        ‘Crypt’ => IlluminateSupportFacadesCrypt::class,
        ‘DB’ => IlluminateSupportFacadesDB::class,
        ‘Eloquent’ => IlluminateDatabaseEloquentModel::class,
        ‘Event’ => IlluminateSupportFacadesEvent::class,
        ‘File’ => IlluminateSupportFacadesFile::class,
        ‘Gate’ => IlluminateSupportFacadesGate::class,
        ‘Hash’ => IlluminateSupportFacadesHash::class,
        ‘Lang’ => IlluminateSupportFacadesLang::class,
        ‘Log’ => IlluminateSupportFacadesLog::class,
        ‘Mail’ => IlluminateSupportFacadesMail::class,
        ‘Notification’ => IlluminateSupportFacadesNotification::class,
        ‘Password’ => IlluminateSupportFacadesPassword::class,
        ‘Queue’ => IlluminateSupportFacadesQueue::class,
        ‘Redirect’ => IlluminateSupportFacadesRedirect::class,
        ‘Redis’ => IlluminateSupportFacadesRedis::class,
        ‘Request’ => IlluminateSupportFacadesRequest::class,
        ‘Response’ => IlluminateSupportFacadesResponse::class,
        ‘Route’ => IlluminateSupportFacadesRoute::class,
        ‘Schema’ => IlluminateSupportFacadesSchema::class,
        ‘Session’ => IlluminateSupportFacadesSession::class,
        ‘Storage’ => IlluminateSupportFacadesStorage::class,
        ‘URL’ => IlluminateSupportFacadesURL::class,
        ‘Validator’ => IlluminateSupportFacadesValidator::class,
        ‘View’ => IlluminateSupportFacadesView::class,
        ‘Form’ => CollectiveHtmlFormFacade::class,
        ‘Html’ => CollectiveHtmlHtmlFacade::class,

        ],

        ];

          • Thanks for reply. kindly check composser.json
            {
            “name”: “laravel/laravel”,
            “description”: “The Laravel Framework.”,
            “keywords”: [“framework”, “laravel”],
            “license”: “MIT”,
            “type”: “project”,
            “require”: {
            “php”: “>=5.6.4”,
            “laravel/framework”: “5.4.*”,
            “laravel/tinker”: “~1.0”,
            “spatie/laravel-permission”: “^2.1”,
            “laracasts/flash”: “^3.0”,
            “laravelcollective/html”: “^5.3.0”,
            },
            “require-dev”: {
            “fzaninotto/faker”: “~1.4”,
            “mockery/mockery”: “0.9.*”,
            “phpunit/phpunit”: “~5.7”
            },
            “autoload”: {
            “classmap”: [
            “database”
            ],
            “psr-4”: {
            “App\”: “app/”
            }
            },
            “autoload-dev”: {
            “psr-4”: {
            “Tests\”: “tests/”
            }
            },
            “scripts”: {
            “post-root-package-install”: [
            “php -r “file_exists(‘.env’) || copy(‘.env.example’, ‘.env’);””
            ],
            “post-create-project-cmd”: [
            “php artisan key:generate”
            ],
            “post-install-cmd”: [
            “Illuminate\Foundation\ComposerScripts::postInstall”,
            “php artisan optimize”
            ],
            “post-update-cmd”: [
            “Illuminate\Foundation\ComposerScripts::postUpdate”,
            “php artisan optimize”
            ]
            },
            “config”: {
            “preferred-install”: “dist”,
            “sort-packages”: true,
            “optimize-autoloader”: true
            }
            }

      • ‘providers’ => [

        /*
        * Laravel Framework Service Providers…
        */
        IlluminateAuthAuthServiceProvider::class,
        IlluminateBroadcastingBroadcastServiceProvider::class,
        IlluminateBusBusServiceProvider::class,
        IlluminateCacheCacheServiceProvider::class,
        IlluminateFoundationProvidersConsoleSupportServiceProvider::class,
        IlluminateCookieCookieServiceProvider::class,
        IlluminateDatabaseDatabaseServiceProvider::class,
        IlluminateEncryptionEncryptionServiceProvider::class,
        IlluminateFilesystemFilesystemServiceProvider::class,
        IlluminateFoundationProvidersFoundationServiceProvider::class,
        IlluminateHashingHashServiceProvider::class,
        IlluminateMailMailServiceProvider::class,
        IlluminateNotificationsNotificationServiceProvider::class,
        IlluminatePaginationPaginationServiceProvider::class,
        IlluminatePipelinePipelineServiceProvider::class,
        IlluminateQueueQueueServiceProvider::class,
        IlluminateRedisRedisServiceProvider::class,
        IlluminateAuthPasswordsPasswordResetServiceProvider::class,
        IlluminateSessionSessionServiceProvider::class,
        IlluminateTranslationTranslationServiceProvider::class,
        IlluminateValidationValidationServiceProvider::class,
        IlluminateViewViewServiceProvider::class,
        SpatiePermissionPermissionServiceProvider::class,
        LaracastsFlashFlashServiceProvider::class,
        CollectiveHtmlHtmlServiceProvider::class,

        /*
        * Package Service Providers…
        */
        LaravelTinkerTinkerServiceProvider::class,

        /*
        * Application Service Providers…
        */
        AppProvidersAppServiceProvider::class,
        AppProvidersAuthServiceProvider::class,
        // AppProvidersBroadcastServiceProvider::class,
        AppProvidersEventServiceProvider::class,
        AppProvidersRouteServiceProvider::class,

        ],

        /*
        |————————————————————————–
        | Class Aliases
        |————————————————————————–
        |
        | This array of class aliases will be registered when this application
        | is started. However, feel free to register as many as you wish as
        | the aliases are “lazy” loaded so they don’t hinder performance.
        |
        */

        ‘aliases’ => [

        ‘App’ => IlluminateSupportFacadesApp::class,
        ‘Artisan’ => IlluminateSupportFacadesArtisan::class,
        ‘Auth’ => IlluminateSupportFacadesAuth::class,
        ‘Blade’ => IlluminateSupportFacadesBlade::class,
        ‘Broadcast’ => IlluminateSupportFacadesBroadcast::class,
        ‘Bus’ => IlluminateSupportFacadesBus::class,
        ‘Cache’ => IlluminateSupportFacadesCache::class,
        ‘Config’ => IlluminateSupportFacadesConfig::class,
        ‘Cookie’ => IlluminateSupportFacadesCookie::class,
        ‘Crypt’ => IlluminateSupportFacadesCrypt::class,
        ‘DB’ => IlluminateSupportFacadesDB::class,
        ‘Eloquent’ => IlluminateDatabaseEloquentModel::class,
        ‘Event’ => IlluminateSupportFacadesEvent::class,
        ‘File’ => IlluminateSupportFacadesFile::class,
        ‘Gate’ => IlluminateSupportFacadesGate::class,
        ‘Hash’ => IlluminateSupportFacadesHash::class,
        ‘Lang’ => IlluminateSupportFacadesLang::class,
        ‘Log’ => IlluminateSupportFacadesLog::class,
        ‘Mail’ => IlluminateSupportFacadesMail::class,
        ‘Notification’ => IlluminateSupportFacadesNotification::class,
        ‘Password’ => IlluminateSupportFacadesPassword::class,
        ‘Queue’ => IlluminateSupportFacadesQueue::class,
        ‘Redirect’ => IlluminateSupportFacadesRedirect::class,
        ‘Redis’ => IlluminateSupportFacadesRedis::class,
        ‘Request’ => IlluminateSupportFacadesRequest::class,
        ‘Response’ => IlluminateSupportFacadesResponse::class,
        ‘Route’ => IlluminateSupportFacadesRoute::class,
        ‘Schema’ => IlluminateSupportFacadesSchema::class,
        ‘Session’ => IlluminateSupportFacadesSession::class,
        ‘Storage’ => IlluminateSupportFacadesStorage::class,
        ‘URL’ => IlluminateSupportFacadesURL::class,
        ‘Validator’ => IlluminateSupportFacadesValidator::class,
        ‘View’ => IlluminateSupportFacadesView::class,
        ‘Form’ => CollectiveHtmlFormFacade::class,
        ‘Html’ => CollectiveHtmlHtmlFacade::class,

        ],

        ];

  17. Thanks for this write up, you saved me many hours of work. I’m having a little problem with the Authorizable Trait tho. right now, when I try to access a controller that uses the trait (let’s say ExampleController), I get “Undefined method “…Controllers\ExampleController::authorize”. Please kindly support.

    • Thats strange, make sure you ExampleController extends base AppHttpControllersController.php


      class ExampleController extends Controller {
      ...
      }

      Since authorize() method comes from AuthorizesRequests trait.

      Let me know how it goes.

  18. Junie Negentien

    Sir, do you have a tutorial base on native laravel auth? Can you make it multiple role permission using the native way? Packages has its own disadvantages I’m looking into some native way. There are some but it doesn’t fit on what Im looking for. Btw, you have the better explaination based on spatie . Thanks for this

  19. Ajaxiome

    Hi,
    One thing i can’t understand is in the Trait Authorizable
    when we call $this->authorize($ability);
    then we call the Laravel’s permission,and not the spatie one’s
    Then for every route i get an Unauthorized Exception, because the $ability is unknow from Laravel core, just known by Spatie’s Tables

    I would imagine in the trait a call to a Spatie Authorize method.

    Do you know how it works ?

    Thx

  20. Fahreza Armando Drakel

    If i run php artisan auth:permission appear
    [SymfonyComponentConsoleExceptionRuntimeException]
    Not enough arguments (missing: “name”).

    How to fix? Thank You

  21. Thank yo for the article. Great stuff.
    Quick question… where should I change the migration file to accomodate UUID for the user_id? In my users table, the users have UUID..

  22. zietbukuel

    Amazing tutorial, I have some problems though. First, when a user is not authorized to see access a resource, I get this error:

    Symfony Component HttpKernel Exception AccessDeniedHttpException
    This action is unauthorized.

    It seems that the Exception handler isn’t doing anything at all, I should be redirected with a flash message, right?

    Second issue is that when I try to create a new user, I get this error:

    Symfony Component HttpKernel Exception MethodNotAllowedHttpException
    No message

    This happens when I hit the submit button.

    Please let me know if you want me to share my code with you. Thanks a lot.

  23. Yudi Purwanto

    Hi, this is bug?

    I have allow user for delete_users and record found in table role_has_permissions

    then in file user/index.blade.php edited like this

    @can(‘edit_users’, ‘delete_users’)

    @include(‘shared._actions’, [
    ‘entity’ => ‘users’,
    ‘id’ => $item->id
    ])

    @endcan

    nothing show action delete

    • Yes, it is a bug. @can syntax does not allow you to pass two permissions like that. It’s invalid. The second parameter supported should be a Model instance. You can do this instead.

      @if (Gate::check(‘edit_users’) || Gate::check(‘delete_users’))
      ….
      @endif

  24. ^C
    C:UsersDineshDownloadsNew folder (2)roles-permissions-laravel-master>php artisan db:seed

    Do you wish to refresh migration before seeding, it will clear all old data ? (yes/no) [no]:
    > yes

    Rolling back: 2017_04_30_014352_create_permission_tables
    Rolled back: 2017_04_30_014352_create_permission_tables
    Rolling back: 2017_04_30_012311_create_posts_table
    Rolled back: 2017_04_30_012311_create_posts_table
    Rolling back: 2014_10_12_100000_create_password_resets_table
    Rolled back: 2014_10_12_100000_create_password_resets_table
    Rolling back: 2014_10_12_000000_create_users_table
    Rolled back: 2014_10_12_000000_create_users_table
    Migrating: 2014_10_12_000000_create_users_table
    Migrated: 2014_10_12_000000_create_users_table
    Migrating: 2014_10_12_100000_create_password_resets_table
    Migrated: 2014_10_12_100000_create_password_resets_table
    Migrating: 2017_04_30_012311_create_posts_table
    Migrated: 2017_04_30_012311_create_posts_table
    Migrating: 2017_04_30_014352_create_permission_tables
    Migrated: 2017_04_30_014352_create_permission_tables
    Data cleared, starting from blank database.
    Default Permissions added.

    Create Roles for user, default is admin and user? [y|N] (yes/no) [yes]:
    >

    ??????? (yes/no) how to set admin login user login?

  25. Is it possible to use the roles with the API:
    Route::middleware(‘auth:api’)->get(‘/user’, function (Request $request)
    How can i test it on Postman?

    Thank you so much

    • Saqueib

      It looks you haven’t imported the App /Permission Model, it’s currently using packages permission model which don’t have defaultPermissions method

  26. Irfan Abdurrasyid

    help me : authorize($ability) not wokfing if use guard admin. on Gate error message
    array:4 [▼
    “ability” => “view_order”
    “result” => false
    “user” => 1
    “arguments” => “[]”
    ]
    i use guard web for customer (use table users) and guard admin for administrator (use table admins). why result in gate always false.

  27. Falak naz

    [SymfonyComponentConsoleExceptionCommandNotFoundException]
    Command “make:model” is not defined.
    Did you mean one of these?
    make:seeder
    make:migration

    i get this error trying to run this command

    php artisan make:model Post -m -c –resource

  28. Hey Saqueib, very nice tutorial! It works very well!
    I just have one question regarding the validation rule of an update method.
    How to flash a error message if the validation fails. I want to keep the syntax with $this->validate

    Is it possible to use something like this?

    $test = $this->validate($request, [
    'name' => 'required|min:2|max:255'
    ]);

    if( $test->failed() )
    {
    flash->error( /*The error*/ )
    }
    else
    {
    /*Proceed to validation*/
    }

    Or I am obligated to use the “old” method by using the Validator model like this
    $validator = Validator::make($request->all(), [
    'name' => 'required|min:2|max:255'
    ]);
    if ($validator->fails()) /*...*/

  29. Yagrademonde

    I have an error : if I check edit_posts and uncheck the others permissions for the User role.

    When I try to access to http://domain/public/posts/4/edit

    I can see the post, but when I want to save my modification, I have the error NotFoundHttpException in Handler.php line 131 : No query results for model [AppPost] 4.

    In my application I wish to not permit to show a list of posts for an user, but with a given url I want to permit user to edit a certain post.

    Can you help me ?