php - Laravel UserPolicy not working properly without models - Stack Overflow

admin2025-05-01  1

I am using Laravel 11.36.1, when I try to get the authorization status in a policy method without model (like the documentation explains) it always returns "false". I tried putting a dd('hello world') to see if it shows something different and it doesn't work.

UserPolicy

<?php

namespace App\Policies;

use App\Models\User;

class UserPolicy
{
    public function create(User $user): bool
    {
        dd('hello word', $user->id);
    }
}

What I'm testing

User::find(2)->can('create'); // Returns `false`
User::find(2)->can('create', User::find(5)); // Returns the dd with `hello world` and `2`
User::find(2)->can('create', User::class); // Returns `false`
User::find(2)->can('create', new User); // Returns the dd with `hello world` and `2`

// Test in Pest
test('example', function() {
    $user = \App\Models\User::factory()->create();

    $this->actingAs($user);

    dd(
        auth()->user()->can('create') // Returns `false`
    );
});

What I'm expecting

User::find(2)->can('create'); // Returns `hello world` and `2`

Some considerations

  • I'm also using Laravel Permission by Spatie (v6.9).
  • I tried to put Gate::policy(User::class, UserPolicy::class) in the boot method of the AppServiceProvider.php, it didn't make any difference.
  • Using User::find(2)->can('create', new User) is neither an optimal, maintainable and aesthetic solution, so I discarded it.
  • Maybe I'm misunderstanding how Policies and Authorizations in Laravel work, but I'm tired of searching and I'm honestly didn't find any explanation.

I am using Laravel 11.36.1, when I try to get the authorization status in a policy method without model (like the documentation explains) it always returns "false". I tried putting a dd('hello world') to see if it shows something different and it doesn't work.

UserPolicy

<?php

namespace App\Policies;

use App\Models\User;

class UserPolicy
{
    public function create(User $user): bool
    {
        dd('hello word', $user->id);
    }
}

What I'm testing

User::find(2)->can('create'); // Returns `false`
User::find(2)->can('create', User::find(5)); // Returns the dd with `hello world` and `2`
User::find(2)->can('create', User::class); // Returns `false`
User::find(2)->can('create', new User); // Returns the dd with `hello world` and `2`

// Test in Pest
test('example', function() {
    $user = \App\Models\User::factory()->create();

    $this->actingAs($user);

    dd(
        auth()->user()->can('create') // Returns `false`
    );
});

What I'm expecting

User::find(2)->can('create'); // Returns `hello world` and `2`

Some considerations

  • I'm also using Laravel Permission by Spatie (v6.9).
  • I tried to put Gate::policy(User::class, UserPolicy::class) in the boot method of the AppServiceProvider.php, it didn't make any difference.
  • Using User::find(2)->can('create', new User) is neither an optimal, maintainable and aesthetic solution, so I discarded it.
  • Maybe I'm misunderstanding how Policies and Authorizations in Laravel work, but I'm tired of searching and I'm honestly didn't find any explanation.
Share Improve this question edited Jan 2 at 23:41 MrCakes asked Jan 2 at 21:10 MrCakesMrCakes 1751 silver badge7 bronze badges 6
  • 1 By default, all gates and policies automatically return false if the incoming HTTP request was not initiated by an authenticated user. – kamlesh.bar Commented Jan 2 at 23:12
  • Hello @kamlesh.bar I made a test with an authenticated user, and the problemas is the same. I modified the question and added the test I runed. Thanks for reply. – MrCakes Commented Jan 2 at 23:44
  • only thing I can think of is give a try by adding \Illuminate\Support\Facades\Gate::define('create', [\App\Policies\UserPolicy::class, 'create']); after $this->actingAs($user); – kamlesh.bar Commented Jan 2 at 23:53
  • @kamlesh.bar now it works, but it's not a fancy way to do it. I want to reach the same result without doing Gate::define(), because it will be more difficult to maintain and I understand Policies are made precisely to accomplish that goal, to manage the Gate::define() logic in a more elegant way, right? – MrCakes Commented Jan 3 at 0:01
  • yes true @MrCakes. There looks to be something wrong with registering policy double check AuthServiceProvider file and check policies / boot method. – kamlesh.bar Commented Jan 3 at 0:05
 |  Show 1 more comment

1 Answer 1

Reset to default 0

I solved the problem. In the Laravel documentation explains that if the ability does not require models, is necessary to pass a reference to the parent model (in my case, User model).

use App\Models\User;

User::find(2)->can('create', User::class); // It works now!
转载请注明原文地址:http://anycun.com/QandA/1746096624a91617.html