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

LaraBABA's avatar

Why can't we use the same request rules in multiple controllers?

Hello,

I have a question regarding policies. In this controller for example, if (with phpstorm) I click on : $this->authorize('updateOwnProfile', $user);

Which is in the "edit" method, I am sent directly to the policy called "UserPolicy.php"

I am not understanding why because this userPolicy.php is not attached anywhere in this page. I see a "$user" variable but not a model.

Any idea how this works please?

Thanks

<?php

namespace App\Http\Controllers;

use App\Http\Requests\UserUpdateRequest;
use App\Models\User;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Spatie\Permission\Models\Role;

class ProfileController extends Controller
{

    /**
     * @param Request $request
     * @param User $user
     */
    public function edit(Request $request){
       $user = Auth::user();
       $this->authorize('updateOwnProfile', $user); <--------------------HERE
       $roles = Role::get();

       return view('app.profile.edit', compact('user', 'roles'));

   }


    /**
     * @param UserUpdateRequest $request
     * @param User $user
     * @return mixed
     * @throws AuthorizationException
     */
    public function update(UserUpdateRequest $request, User $user)
    {
        $this->authorize('update profile', $user);

        $validated = $request->validated();

        if (empty($validated['password'])) {
            unset($validated['password']);
        } else {
            $validated['password'] = Hash::make($validated['password']);
        }

        if ($request->hasFile('avatar')) {
            if ($user->avatar) {
                Storage::delete($user->avatar);
            }

            $validated['avatar'] = $request->file('avatar')->store('public');
        }

        $user->update($validated);

        $user->syncRoles($request->roles);

        return redirect()
            ->route('profile.edit', $user)
            ->withSuccess(__('crud.common.saved'));
    }
}

0 likes
14 replies
martinbean's avatar
Level 80

@user476820 Policies aren’t tied to controllers. They’re tied to models. Policies are associated with a model in your AuthServiceProvider.

So I imagine your IDE is reading the $user parameter, detecting it’s an instance of your User model, and sending you to the policy associated with that model.

1 like
LaraBABA's avatar

@martinbean Thanks Martin, yes and it looks it comes from this:

        Gate::guessPolicyNamesUsing(function ($modelClass) {
            return 'App\Policies\' . class_basename($modelClass) . 'Policy';
        });

        $this->registerPolicies();
LaraBABA's avatar

@martinbean Something I would like to ask you Martin please.

What if I want to share a rule request between 2 controllers?

UserController.php
public function update(UserUpdateRequest $request, User $user){
}




ProfileController.php
public function update(UserUpdateRequest $request, User $profile){
}

It looks like it is not possible to use "UserUpdateRequest" in both.

LaraBABA's avatar

@martinbean I understand, I had to create a new model called "profile" but still it makes no sense, why can't you use the same policies with 2 model's request in a single controller?

I understand it is not tied to the controller but model, but my usage is inside a controller. I have to duplicate my policy code to attach it to another model, surely there is something much cleaner than duplication no?

martinbean's avatar

@User476820 I don’t understand what you’re trying to do? You keep going on about different models, requests, controllers… A policy is tied to a model. That’s it. You can use the policy where ever you use the model type it corresponds to.

LaraBABA's avatar

@martinbean Very surprising that there is not a way to use 1 policy with 2 models, especially on super long and complicated forms which may require the same policies.

martinbean's avatar

@User476820 Why would you want to use a policy for two models?

I don’t think you really understand policies, since you kept going on about trying to associate them with controllers, and now you’re complaining you can’t re-use them with more than one model. Maybe have a re-read through the docs on policies.

From https://laravel.com/docs/9.x/authorization#creating-policies:

Policies are classes that organize authorization logic around a particular model or resource.

LaraBABA's avatar

@martinbean, I think I know the misunderstanding between us...... I meant "request access"(eg:rules).

In this example:

UserController.php
public function update(UserUpdateRequest $request, User $user){
}

ProfileController.php
public function update(UserUpdateRequest $request, User $profile){
}

The "UserUpdateRequest"(or rules) is my problem. I cannot reuse it.

LaraBABA's avatar

It is fine, no worries, I will just duplicate the rules into another "ProfileUpdateRequest" as I am losing too much time on this particular issue. I prefer to duplicate the rules into other files than waste more time on this matter.

martinbean's avatar

I think I know the misunderstanding between us...... I meant "request access"(eg:rules).

@User476820 What has this got to do with policies, which is what you originally asked about?

LaraBABA's avatar

@martinbean Sometimes, it happens, you mix up the terminology......we are all Humans no? I always get confused in English with the Laravel terminology. I wish I could delete the thread but the forum won't let me. Instead of policies I meant "requests rules". I realised that this(policy) $this->authorize('updateOwnProfile', $user); was not the problem but the actual rule request(later on)

LaraBABA's avatar

It is ok, just do not bother answering as it is all mixed up now as I thought the original issue was a policy issue but then based on another post I wrote in the forum, I realized it was an actual request rule issue.

Please or to participate in this conversation.