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

warpig's avatar
Level 12

Invokable controller not being used on a form

Im using an invokable controller because I want to assign an ability to a role, and for this Im trying to pass the ID value of an ability, and then assign it to a role. In my database I have these tables:

  1. Roles
  2. Roles_user
  3. Abilities
  4. Ability_role

Ability_role table has 2 columns; role_id and ability_id here an ability is associated to a role.

I want to be able to write an association on this table by using a method that I have on my Role model which is this:

    public function allowTo($ability)
    {
        $this->abilities()->sync($ability, false);
    }

But I get a Not Found message and this on the URI:

http://videotheque.test/assignAbility?abilities[]=2

So it means the controller im using it's not being used. This is what I do and what I have:

  1. Through a select element, I print out the current abilities and then a button to submit the form
  2. The option value on the select, points to the ID stored in the database
  3. In my web routes I have an invokable controller being listed with a post method 4- On my ``AbilitiesRoleController``` I have created a method which should accept the request
  4. After the request is received, the role should now have a new ability assigned

roles-tab.blade.php

<form 
    action="/assignAbility"
    model="POST"
>
    <select 
        name="abilities[]" 
        id="abilities"
        multiple
    >
        @foreach ($abilities as $ability)
            <option value="{{ $ability->id }}">
                {{ $ability->name }}
            </option>
        @endforeach
    </select>

    <button 
        type="submit">
        Assign
    </button>
</form>

web.php

    Route::post('/assignAbility', AbilitiesRoleController::class);

AbilitiesRoleController.php

    public function __invoke(Request $request, Role $role, Ability $abilities)
    {
        dd($abilities);

        $abilities = request()->validate([
            'ability_id' => ['required']
        ]);

        foreach ($request->abilities as $ability) {
            $role->allowTo($ability);
        }
    }

Whenever an ability has been selected and submitted through the form the method from AbilitiesRoleController.php should receive this data and write on the database, assigning a new ability to a particular role.

Instead a 404 page is displayed and I notice that the URI shows this: http://videotheque.test/assignAbility?abilities[]=2 which seems to me that the controller that I assign on the routes, is not even being used correctly so the method is not even called.

It's a Laravel 8 project. Thanks!

0 likes
14 replies
apex1's avatar

What is <form model="POST"> ...?

tykus's avatar

First the attribute is method:

<form 
    action="/assignAbility"
    method="POST"
>

Then, use attach instead of sync if passing only one ability ID; otherwise you could just pass the array into the allowTo method:

$role->allowTo($request->abilities );
warpig's avatar
Level 12

@tykus Yes, the method should be able to pass 1 or multiple abilities that's why I changed it like you mention where an array is allowed in the request however it cannot find the "assignAbility" route.

    public function __invoke(Request $request, Role $role)
    {
        foreach ($request->ability as $abilities) {
            $role->allowTo($request->$abilities);
        }
    }
tykus's avatar

If it accepts an array, then do not iterate:

$role->allowTo($request->abilities);
tykus's avatar
tykus
Best Answer
Level 104

What is the purpose of the typehinted Role in the method signature; there is no corresponding wildcard segment{role} in the URI, e.g.

Route::post('roles/{role}/assignAbility', AbilitiesRoleController::class);
<form action="/roles/{{ $role->id }}/assignAbility" method="POST">
tykus's avatar

Is this a ModelNotFoundException, or a Routing issue - have you cached your routes?

warpig's avatar
Level 12

I think it's a routing issue, it just says "404 Not Found", check image: https://imgur.com/U9ETXwE

have you cached your routes?

I don't know what that is, sorry.

tykus's avatar

Is the URL correct? The first segment was roles above - you have role in devtools. Make sure the form is submitting to the Route you have defined.

warpig's avatar
Level 12

I can see that now but it is still returning a 404 dialog

warpig's avatar
Level 12

I think it's returning the $roles variable first instead of going for the $abilities, https://imgur.com/XGk1Q7m Im only displaying the roles for better representation but I see that that is a problem

                @foreach ($roles as $role)
                    <div>

                        <p>{{ $role->name }}</p>
                        
                        <form 
                            action="/roles/{{ $role->id }}/assignAbility"
                            method="POST"
                        >
                            <select 
                                name="abilities[]" 
                                id="abilities"
                                multiple
                            >
                                @foreach ($abilities as $ability)
                                    <option value="{{ $ability->id }}">
                                        {{ $ability->name }}
                                    </option>
                                @endforeach
                            </select>

                            <button 
                                type="submit">
                                Assign
                            </button>
                        </form>

                    </div>
                @endforeach

I mean, if I click on the first option and had selected an ability regardless of the ability, it always shows 1 in the URI, it shows a 2 if i click on any ability for the "moddy" role. See what I mean? So having the $roles variable is affecting the form ??

EDIT

Fundamentally wrong:

  1. Form doesn't have the @csrf token
  2. Routing is wrong (explained below)

Question was this: Invokable controller not being used on a form

Quick guide through:

  1. Assigning an ability to a role needs to have a few things like:

a) recovering the existing role which we will want to pass an ability to

b) fetching the ability value (ID)

c) hopefully using a method from the Role model, this was the way I had it set up and I got it following the Laravel 6 from scratch lessons (now archived): https://laracasts.com/series/laravel-6-from-scratch/episodes/54

If you don't encounter any of the points listed on the "fundamentally wrong" list, make sure to follow the reply marked as "best answer" and build from there.

The "quick guide through" it's just that, a really quick rundown of what is expected on the method it's not meant to be a Full-guide, lol.

tykus's avatar

@warpig you have so many different threads for this issue, it is difficult to keep up with the different advice you have been given...

warpig's avatar
Level 12

I know that, which is why Im mainly trying to answer the answer of the title post and explaining the context a little bit, maybe edit your original reply so that can be answered there as well if you feel like doing so, so that I can remove that, but do you think explaining the context is wrong, counterproductive? Please let me know.

Please or to participate in this conversation.