Blog: PHP

Policies and Route::apiResource in Laravel


While I’ve been a PHP developer for 20 years, Laravel is a new area for me, and I must say, am as happy as the proverbial pig. But I did encounter a really head-scratching quirk when working with the authorizeResource call from a Controller.

So here’s the back story… I have a Model called UserDelegation (where a User can delegate responsibilities to another User for a period of time), and that in turn has an associated FormRequest, Resource, Policy and pair of Controllers – one for admin, and one for normal users – you know, all the good practice components.

When creating the UserResource migration, the necessary Permissions are added to the database too so that I can include logic in my UserDelegationPolicy. All hunky dory so far.

In my api.php file, I am adding my routes as an API resource:

Route::apiResource('delegations', 'Manager\UserDelegationController');

When Laravel defines my routes, I am getting the expected GET, POST, DELETE and PUT endpoints for the “delegations” route – which is excellent.

In my controller, in its constructor, am calling authorizeResource

public function __construct()

But when I try to access the endpoints, I receive a 403 error. Why? My other policies for other Models, such as “Title” or “Organisation” are working as expected. My Policy is using the correct permissions for the new Model, so what gives? Head scratching moment, and Google wasn’t helping, so time to explore the Laravel source to get a better understanding of what is going on.

Looking at the authorizeResource call, this accepts multiple arguments, starting with the Model’s class name. Makes sense so far. But also more arguments, the second called $parameter, which I had never actually used.

This is where the issue stems from, and is definitely a user error.

If you do not include $parameter, the authorizeRequest function will create a snake-case $parameter based on the base name of the Model – so in this instance, it would set $parameter to be “user_delegation”.

However, in my route definitions, Laravel has defined the route parameter as “delegation”, creating a singular representation of my route name. What I mean is that my route looks like:


But you see that authorizeRequest, without explicitly setting $parameter, has “guessed” that it would be “user_delegation”. This means that it would fire for a route like:


When I try to call my endpoint, it is not matching because my route is defined with “delegation” but Laravel’s authorisation is expecting “user_delegation”.

How to fix this… well there are two ways to approach this:

  • Explicitly define $parameter with the authorizeResource call
  • Explicitly define the parameter used in the route definition

Be explicit with in the controller

Quite simply, when authorising your Controller, explicitly give it the parameter to look for in the route.

public function __construct()
    $this->authorizeResource(UserDelegation::class, 'delegation');

While Laravel’s documentation does include reference to this, which I eventually found, to me it didn’t read as obvious as it may be should have. But when you stop and re-read it, it does tell you exactly what you need to know.

Be explicit with in the route definition

This one is a little more wordy to prepare, and means you’re adding the $options array to your route definition, and passing the parameters array with the definition that “delegation” should actually be “user_delegation”.

Route::apiResource('delegations', 'Manager\UserDelegationController', [
    'parameters' => [
        'delegation' => 'user_delegation'

This makes sense too, and could be useful if you have a really different approach to naming conventions, but does make the api.php routes file less readable (if you ask me). I love the simplicity of my routes file with such clean and easy-to-scan apiResource calls.

Which is better?

Well… I’m undecided – both solve the problem, but as to “better”, that might be more of a coding style question for the project. What do you think? What solution reads better?

I feel that the authorizeResource solution may be easier to write, and a better habit to have, by being explicity with every single authorizeResource call simply passing the $parameter. That seems a simpler best-practice with an easier-to-read api.php routes file. But happy to hear your thoughts too.


View all

2020: refreshing the life of a long term developer

2020 has been incredibly refreshing. Let’s also be blunt, it’s been completely shit for so many too – including isolation from family and months of Stage...

Continue reading...


Astro's Playroom

Astro’s Playroom. It’s free, and comes pre-installed on your PS5. It is basically a tech demo wrapped up in a platformer. And a pretty fun platformer too. And...

Continue reading...


Creating a TinyMCE addon for Statamic 3

It’s no secret: I do love TinyMCE. It provides an excellent authoring experience, that produces clean and reliable HTML, and can easily be customised and extended...

Continue reading...


Installing and review of the Sonos Wall Mount with the Sonos One SL

I’m new to the Sonos ecosystem, and after setting up the Sonos Arc and Sub combination, I wanted more, so splurged on a pair of One SL speakers for surrounds....

Continue reading...

I am the Development Director (and co-owner) at Mity Digital, a Melbourne-based digital agency specialising in responsive web design, custom web development and graphic design.
Mity Digital