spkvn
spkvn

Reputation: 194

Laravel 5.4 MethodNotAllowedHttpException

Having trouble with a route with two variables. I've got a form to delete an item.

<form action="/admin/room/{{$room->id}}/image/{{$img->id}}/">
    {{method_field('DELETE')}}
    {{csrf_field()}}
    <input class="btn btn-danger" type="submit" value="Delete">
</form>

Upon clicking Delete, I get a MethodNotAllowedHttpException.

Here's my routes file.

//authenticated users only
Route::group(['middleware' => 'auth'], function ()
{
    Route::prefix('admin')->group(function () 
    {
        /*Some other routes*/

        //Matches "/admin/room/{room}/image[s]?"
        Route::get('room/{room}/image', 'RoomImagesController@index')
        ->name('admin.roomimages');
        Route::get('room/{room}/image/create','RoomImagesController@create');
        Route::post('room/{room}/image','RoomImagesController@store');
        Route::delete('room/{room}/image/{image}','RoomImagesContoller@destroy');

        //Matches the "/admin/room[s]?" URL
        Route::get('/rooms', 'AdminController@rooms');      
        Route::get('/room/create', 'RoomController@create');
        Route::get('/room/{room}', 'RoomController@edit');  
        Route::post('/room/search','RoomController@search');
        Route::post('/room/store', 'RoomController@store'); 
        Route::post('/room/{room}','RoomController@update');    
        Route::delete('/room/{room}','RoomController@destroy');
        
        /*some more routes.*/
    }
}

And my RoomImagesController class

class RoomImagesController extends Controller
{
    /*Other Methods*/
    public function destroy(Room $room, RoomImage $image)
    {
        dd($room, $image);
    }
}

The URL I'm sent to is:

http://domain.name/admin/room/1/image/1?_method=DELETE&_token=/*tokenValue*/

Not sure why I'm having issues here! If anyone could shed some light I'd appreciate it. Let me know if you need any more information.


Edit

I've added method="post" to the form, with the same error. Here's a raw paste from the webpage.

<form method="post" action="/admin/room/1/image/4/">
    <input name="_method" value="DELETE" type="hidden">
    <input name="_token" value="lFrYPuzz8pY4EEJZEKCtZgjGM4dkk6uTD3p0jhpK" type="hidden">
    <input class="btn btn-danger" value="Delete" type="submit">
</form>

Edit 2

Named routes seemed like a solution!

//web.php
Route::post('room/{room}/image/{image}','RoomImagesContoller@delete')
    ->name('admin.deleteRoomImages');

//x.blade.php
<form action="{{ route('admin.deleteRoomImages', [ 
                        'room'  => $room->id, 
                        'image' => $img->id ]) }}/"
      method="POST">
    {{ method_field('DELETE') }}
    {{ csrf_field() }}
    <input class="btn btn-danger" type="submit" value="Delete">
</form>

But I still get the MethodNotAllowedError

It may be worth noting when I ran php artisan route:list I've found that i get a ReflectionError 'RoomImagesController does not exist' I'll investigate this further!

Upvotes: 2

Views: 605

Answers (6)

Ajay Kumar
Ajay Kumar

Reputation: 1352

this is happening because you are making a request to wrong url

it must be action="/admin/room/{{$room->id}}/image/{{$img->id}}" not action="/admin/room/{{$room->id}}/image/{{$img->id}}/"

why it is happening you made a request to action="/admin/room/1/image/4/" which is being showing moved to action="/admin/room/1/image/4" and you lose method field which is DELETE that's why you are getting error try to use below example and it will work fine.

<form action="/admin/room/{{$room->id}}/image/{{$img->id}}" method="post">
    {{method_field('DELETE')}}
    {{csrf_field()}}
    <input class="btn btn-danger" type="submit" value="Delete">
</form> 

Upvotes: 3

omitobi
omitobi

Reputation: 7334

Add method="post" as an attribute to your form. Like so:

<form action="/admin/room/{{$room->id}}/image/{{$img->id}}" method="post">

If the method attribute is not provided, the form is submitted via GET by default. DELETE method requires the data to be submitted via POST.

Upvotes: 5

Kunsal Ajay
Kunsal Ajay

Reputation: 179

Run composer dump-autoload to clear the ReflectionException. If you copied the class file and modified it, verify that the name of the class is RoomImagesController and run composer dump-autoload. Good luck!

Upvotes: -1

linktoahref
linktoahref

Reputation: 7972

You could use Named Routes

Route::delete('room/{room}/image/{image}',
              'RoomImagesContoller@destroy')->name('deleteRoomImages');

and use the route() helper method in your form

<form action="{{ route('deleteRoomImages', [ 
                'room'  => $room->id, 
                'image' => $img->id ]) }}/" method="POST">
    {{ method_field('DELETE') }}
    {{ csrf_field() }}
    <input class="btn btn-danger" type="submit" value="Delete">
</form>

Upvotes: 1

Pankaj Makwana
Pankaj Makwana

Reputation: 3050

You can do it by POST method by passing method="POST" and add delete method hidden field inside the form tag

<form action="/admin/room/{{$room->id}}/image/{{$img->id}}/" method="post">
    {{method_field('DELETE')}}
    {{csrf_field()}}
    <input class="btn btn-danger" type="submit" value="Delete">
</form>

Upvotes: 0

Michael Oshosanya
Michael Oshosanya

Reputation: 134

Set a method attribute on the form to POST So you have

<form action="/admin/room/{{$room->id}}/image/{{$img->id}}/" method="POST">
    {{method_field('DELETE')}}
    {{csrf_field()}}
    <input class="btn btn-danger" type="submit" value="Delete">
</form>

Upvotes: 1

Related Questions