Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

VinayPrajapati's avatar

Multiple Policy For User Model

I have different permissions like this

'view-admin'
'create-admin'
'edit-admin'
'delete-admin'

'view-student',
'create-student'
'edit-student'
'delete-student'

'view-teacher'
'create-teacher'
'edit-teacher'
'delete-teacher'

i register policy in my AuthServiceProvider

<?php

namespace App\Providers;

use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        'App\Models\User' => 'App\Policies\Admin\AdminPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();
    }
}


in my AdminPolicy

<?php

namespace App\Policies\Admin;

use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;

class AdminPolicy
{
    use HandlesAuthorization;

    /**
     * Determine whether the user can view any models.
     *
     * @param  \App\User  $user
     * @return mixed
     */
    public function viewAny(User $user)
    {
        if ($user->can('view-admin')) {
            return true;
        }
    }

    /**
     * Determine whether the user can view the model.
     *
     * @param  \App\User  $user
     * @param  \App\User  $model
     * @return mixed
     */
    public function view(User $user, User $model)
    {
        if ($user->can('view-admin')) {
            return true;
        }
    }

    /**
     * Determine whether the user can create models.
     *
     * @param  \App\User  $user
     * @return mixed
     */
    public function create(User $user)
    {
        if ($user->can('create-admin')) {
            return true;
        }
    }

    /**
     * Determine whether the user can update the model.
     *
     * @param  \App\User  $user
     * @param  \App\User  $model
     * @return mixed
     */
    public function update(User $user, User $model)
    {
        if ($user->can('edit-admin')) {
            return true;
        }
    }

    /**
     * Determine whether the user can delete the model.
     *
     * @param  \App\User  $user
     * @param  \App\User  $model
     * @return mixed
     */
    public function delete(User $user, User $model)
    {
        if ($user->can('delete-admin')) {
            return true;
        }
    }

    /**
     * Determine whether the user can restore the model.
     *
     * @param  \App\User  $user
     * @param  \App\User  $model
     * @return mixed
     */
    public function restore(User $user, User $model)
    {
        //
    }

    /**
     * Determine whether the user can permanently delete the model.
     *
     * @param  \App\User  $user
     * @param  \App\User  $model
     * @return mixed
     */
    public function forceDelete(User $user, User $model)
    {
        //
    }
}

i have role admin,student,teacher. i want to make policy for student and teacher, How can i achieve this.

0 likes
14 replies
VinayPrajapati's avatar

How can i make policy for user, Like, StudentPolicy and TeacherPolicy For User Model, Or Some other option.

martinbean's avatar

@vinayprajapati You can’t have multiple policies for a user. A policy just defines what actions a user can perform.

If you have multiple policies attached to a User model, then how is Laravel supposed to know which one to invoke at any one time?

martinbean's avatar
Level 80

@vinayprajapati No, because you’re approaching polices the wrong way. You create policies for resources, not a user class. The policy checks if the authenticated user can perform the requested action of the target resource, so it’s in these policy methods that you would check permissions.

Take an article. Imagine an admin user can update any article, and the author can update only their own articles. The corresponding article policy method may look like this:

class ArticlePolicy
{
    public function update(User $user, Article $article)
    {
        // Admins can update any article
        if ($user->isAdmin()) {
            return true;
        }

        // Authors can update their own articles only
        if ($user->is($article->author)) {
            return true;
        }

        // If neither checks pass, user cannot update article
        return false;
    }
}

You can then use this policy in your controller method:

class ArticleController extends Controller
{
    public function update(UpdateArticleRequest $request, Article $article)
    {
        // Will call ArticlePolicy::update
        $this->authorize('update', Article::class);

        $article->update($request->validated());

        // Return response
    }
}
VinayPrajapati's avatar

I want to authorized policy by permissions,

I have super-admin who have all rights,

AdminPolicy works fine for single admin role.

admin can

create-teacher, update-teacher, etc // Super admin assign permission

teacher can

create-student, update-student, etc // Super admin assign permission

student can

view-student, view-teacher, etc // Super admin assign permission

i have users with role admin, teacher and student.

for student and teacher i want make policy but may be it's not possible.

Now i check in every method for seprate permission for StudentController and TeacherController

<?php

namespace App\Http\Controllers\User;

use App\Actions\Student\AddStudent;
use App\Actions\Student\UpdateStudent;
use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class StudentController extends Controller
{

    /**
     * Instantiate a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
        abort_if(! auth()->user()->can('create-student'), 403);
        $user = AddStudent::add($request->all());
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Models\User  $student
     * @return \Illuminate\Http\Response
     */
    public function edit(User $student)
    {
        abort_if(! auth()->user()->can('edit-student'), 403);
        $student = User::find($student->id);
        return response()->json([
            'student' => $student,
        ]);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\User  $student
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, User $student)
    {
        abort_if(! auth()->user()->can('edit-student'), 403);
        $student = UpdateStudent::update($request->all(), $student);
        
        return response()->json([
            'student' => $student
        ]);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\User  $student
     * @return \Illuminate\Http\Response
     */
    public function destroy(User $student)
    {
        abort_if(! auth()->user()->can('delete-student'), 403);
        $student->delete();

        return response()->json([
            'success' => $student
        ]);
    }
}

Any other optimal solution.

jrdavidson's avatar

Just as an aside. You can improve the readability of these lines.

abort_if(! auth()->user()->can('delete-student'), 403);

to

abort_if(auth()->user()->cannot('delete-student'), 403);
1 like
VinayPrajapati's avatar

Insted of call in every methods in controller, how can i refactore to another file like policy?

martinbean's avatar

@vinayprajapati Again, you’re thinking about your policies the wrong way. You should have a StudentPolicy class that checks if the authenticated user can perform actions such as updating or deleting a student model. You can check your permissions in these policies:

class StudentPolicy
{
    public function update(User $user, Student $student)
    {
        // Check if the given user can update the given student
    }
}
class StudentController extends Controller
{
    public function update(UpdateStudentRequest $request, Student $student)
    {
        // Will invoke StudentPolicy::update method
        // 403 error will be returned if policy check fails
        $this->authorize('update', $student);

        $student->update($request->validated());

        // Return response
    }
}

If a “super admin” can do everything, then you can add a policy filter that just returns true for any policy check so you don’t need to repeat it in all of your policy methods:

public function before(User $user, $ability)
{
    if ($user->isSuperAdmin()) {
        return true;
    }
}

Might be worth reading the section on authorisation in the Laravel docs a bit more.

VinayPrajapati's avatar

	/**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        'App\Models\User' => 'App\Policies\Admin\AdminPolicy',
    ];

// Will invoke StudentPolicy::update method

 $this->authorize('update', $student);  // Will invoke AdminPolicy::update method not  StudentPolicy::update 
martinbean's avatar

@vinayprajapati Are you reading any of what I’m typing?

You don’t have a “user” policy or an “admin” policy. You have a policy for the model (i.e. student) that you’re trying to perform actions against.

VinayPrajapati's avatar

@martinbean Yes,

I'm reading your reply,

I have only one User Model with different role based user.

i want to give specific permission to all role based user and authorize by policy

Aridez's avatar

@martinbean I found myself in the same situation. The problem is that there is different logic attached to the controllers too, so a resource is being treated differently depending on the user role, and each user role has a controller assigned to them.

Seems like Laravel policies are not a solution fully compatible with the use of roles, but I would like to find a clean way to handle these cases, everything is detailed in my question here:

VinayPrajapati's avatar

@martinbean


can you sugggest for this scenario.

i given permission to User Model based on role, authorized by policy.

Super Admin (Role Super Admin - User Model)  

1. Have all rights,

Admin (Role Admin - User Model)  

1. 'view-student',
2. 'create-student'
3. 'edit-student'
4. 'delete-student'

5. 'view-teacher'
6. 'create-teacher'
7. 'edit-teacher'
8. 'delete-teacher'

Teacher (Role Teacher- User Model)  

Given permission

1. 'view-student',
2. 'create-student'
3. 'edit-student'

Here teacher can't delete student

Student (Role Student - User Model)

1. 'view-student'

2. 'view-teacher'

Please or to participate in this conversation.