The Guest User Gates introduced in Laravel 5.7 work only if you pass a _function_ callback when defining the gate ability. If a string is provided (Class@method) they do not work.
I have researched about how the Gate works and I think the issue comes from this line:
https://github.com/laravel/framework/blob/db6d5cb0ebf0901c0e27f292810835f9bfe4c0a6/src/Illuminate/Auth/Access/Gate.php#L489
When passing the ability to the canBeCalledWithUser method, the ability is already a closure as the define method transforms it using the buildAbilityCallback. So when checking if the canBeCalledWithUser, methodAllowsGuests is never called as $class is never an array, it's already a closure:
Define a gate using a Class@method style callback:
\Gate::define('user.view', 'App\Policies\UserPolicy@view');
// UserPolicy.php
class UserPolicy {
public function view(?User $user, Product $product) {
dd('I am never called');
}
}
However, this works:
\Gate::define('user.view', function(?User $user, Product $product) {
dd('I am called');
});
Hi @IsraelOrtuno, you should check this method;
When you passing to class@method, this method return user.view. So trying to run App\Policies\[email protected] but don't work because user.view method does not exists
So you mean that abilities should be camelCased? I get the same behaviour whatever the ability is called.
No. I mean, if you pass to callback instead of class@method, gate trying to find ability on policy class. In this example gate trying to work [email protected]. If you replaced ability with view, it is work. Or you replaced ability with user-view and replaced method with userView, works again.
I can reproduce this.
@driesvints This is fixed.
Most helpful comment
I can reproduce this.