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

AlwinL's avatar
Level 1

Laravel 11 policy not auto-detected unless model is passed

I have an Employer model + controller + policy, all located and named as per the docs and the policy is auto-detected and implemented as expected just fine. Well sort of, using the code below, 'view' is authorized ok, but 'create' is not (is always 'unauthorized').

class EmployerPolicy
{
	public function view(User $user, Employer $employer): bool
	{
		return true;
	}

	public function create(User $user): bool
	{
		return true;
	}
}


class EmployerController extends Controller
{
	public function show(Employer $employer)
	{
	   Gate::authorize('view', $employer);       
	   return view('employer.show', ['employer'=> $employer]);
	}

	public function create()
	{
		Gate::authorize('create');

		return view('employer.create');
	}
}

The only way I can get it to work is by passing an Employer object into the policy, something like below (for 'create'):

class EmployerPolicy
{
	public function view(User $user, Employer $employer): bool
	{
		return true;
	}

	public function create(User $user, Employer $employer): bool
	{
		return true;
	}
}


class EmployerController extends Controller
{
	public function show(Employer $employer)
	{
	   Gate::authorize('view', $employer);       
	   return view('employer.show', ['employer'=> $employer]);
	}

	public function create()
	{
		$employer = new Employer();
		Gate::authorize('create', $employer);

		return view('employer.create');
	}
}

I haven't seen this behaviour mentioned anywhere, in my mind if the policy file is auto-detected then any of the policy methods should work, but it appears that it only works when an instance of the model is passed into 'authorize'. Is this expected behaviour?

0 likes
3 replies
tykus's avatar
tykus
Best Answer
Level 104

By convention, the Policy method for a create action is not expecting a Model instance, so remove that from the signature:

public function create(User $user): bool
{
    return true;
}

https://laravel.com/docs/11.x/authorization#methods-without-models

Instead, pass the class name to the authorization check, and the class name will be used to determine which policy to use when authorizing the action

Gate::authorize('create', Employer::class);

https://laravel.com/docs/11.x/authorization#user-model-actions-that-dont-require-models

AlwinL's avatar
Level 1

Thank you! I get it, obviously I misunderstood the bit about 'methods without models'.

It still does feel weird to me that a model is needed because the policy file has already been determined by naming convention, so should be irrelevant.

tykus's avatar

@AlwinL the Model class name is needed whenever you use the Gate::authorize() method, or auth()->user()->can() method for Policy methods that do not need a Model instance. Otherwise, there is nothing to hint at the Model the user intends to create. Like I said above, the Policy create method does not need the Model instance;

Anyway, if you're all set, please mark the thread solved.

Please or to participate in this conversation.