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

zaster's avatar

MethodNotAllowedHttpException in RouteCollection.php

web.php

Route::prefix('employee')->group(function () {    

//More Routes

    //POItem Section
    Route::post('/poitem/create', 'Employee\POItemController@create')->name('employee.poitem.create');
    Route::get('/poitem/pending', 'Employee\POItemController@pendingList')->name('employee.poitem.pendinglist');
    Route::delete('/poitem/{poitem}', 'Employee\POItemController@destroy')->name('employee.poitem.destroy');
}

POItemController.php

    public function destroy($id)
    {        
        $po_item = POItem::find($id);
        $po_item->delete();
        return back()->with('success','Information has been  deleted');
    }  

poitems.create.blade.php

<div class="col-md-1">
  <form action="{{action('Employee\POItemController@destroy', $po_item->id)}}" method="post">
      {{csrf_field()}}
      <input name="_method" type="hidden" value="DELETE">
      <button class="btn btn-danger" type="submit">Delete</button>
   </form>
</div>

0 likes
31 replies
roerjo's avatar

The hidden input field looks correct...maybe try {{ method_field('DELETE') }} instead?

roerjo's avatar

If you inspect the HTML in the browser, is the form action URL generated properly?

zaster's avatar

I think its something to do with the routes

roerjo's avatar

@ZASTER - Can you post the rendered HTML so we can confirm that the URL is correct?

zaster's avatar

@roerjo

<div class="col-md-1">                                        
 <form action="http://pk19.test/employee/poitem/2" method="post">
  <input type="hidden" name="_token" value="wZVaD2F8XcrokdJjlA1XzlBxuucNQpiDnm1Qfpdq">
  <input name="_method" type="hidden" value="DELETE">
  <button class="btn btn-danger" type="submit">Delete</button>
 </form>
 </div>
roerjo's avatar

@ZASTER - Hmm everything looks good there...can you post the stack trace? Are there any other routes that have non-get/post verbs such? If so, are those working?

zaster's avatar

@roerjo

C:\laragon\www\pk19\vendor\laravel\framework\src\Illuminate\Routing\RouteCollection.php
        if ($request->method() == 'OPTIONS') {
            return (new Route('OPTIONS', $request->path(), function () use ($methods) {
                return new Response('', 200, ['Allow' => implode(',', $methods)]);
            }))->bind($request);
        }
 
        $this->methodNotAllowed($methods);
    }
 
    /**
     * Throw a method not allowed HTTP exception.
     *
     * @param  array  $others
     * @return void
     *
     * @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
     */
    protected function methodNotAllowed(array $others)
    {
        throw new MethodNotAllowedHttpException($others);
    }
 
    /**
     * Get routes from the collection by method.
     *
     * @param  string|null  $method
     * @return array
     */
    public function get($method = null)
    {
        return is_null($method) ? $this->getRoutes() : Arr::get($this->routes, $method, []);
    }
 
    /**
     * Determine if the route collection contains a given named route.
     *
     * @param  string  $name
     * @return bool
     */
    public function hasNamedRoute($name)
Arguments
""

web.php

//EMPLOYEE SECTION
Route::prefix('employee')->group(function () {    
        

    Route::get('/login', 'Auth\AuthEmployee\LoginController@showLoginForm')->name('employee.login');
    Route::post('/login', 'Auth\AuthEmployee\LoginController@login')->name('employee.login.submit');
    Route::post('/logout', 'Auth\AuthEmployee\LoginController@logout')->name('employee.logout');
    Route::get('/password/reset', 'Auth\AuthEmployee\ForgotPasswordController@showLinkRequestForm')->name('employee.password.request');
    Route::post('/password/email', 'Auth\AuthEmployee\ForgotPasswordController@sendResetLinkEmail')->name('employee.password.email');
    Route::get('/password/reset/{token}', 'Auth\AuthEmployee\ResetPasswordController@showResetForm')->name('employee.password.reset');
    Route::post('/password/reset', 'Auth\AuthEmployee\ResetPasswordController@reset');

    
    Route::get('/', 'Employee\EmployeeController@index')->name('employee.home');
    Route::get('/usermanual', 'Employee\PageController@userManual')->name('employee.usermanual');
    

    //Item Section
    Route::post('/item', 'Employee\ItemController@store')->name('employee.item.store');
    Route::get('/item', 'Employee\ItemController@index')->name('employee.item.index');
    Route::get('/item/create', 'Employee\ItemController@create')->name('employee.item.create');
    Route::get('/item/json-items/{id}','Employee\ItemController@fetchItems');

    //Item Category Section
    Route::post('/item/category', 'Employee\ItemCategoryController@store')->name('employee.itemcategory.store');
    Route::get('/item/category', 'Employee\ItemCategoryController@index')->name('employee.itemcategory.index');
    Route::get('/item/category/create', 'Employee\ItemCategoryController@create')->name('employee.itemcategory.create');

    //Job Section
    Route::post('/job', 'Employee\JobController@store')->name('employee.job.store');
    Route::get('/job', 'Employee\JobController@index')->name('employee.job.index');
    Route::get('/job/create', 'Employee\JobController@create')->name('employee.job.create');
    Route::get('/job/{job}/edit', 'Employee\JobController@edit')->name('employee.job.edit');
    
    //Job Costing Section
    Route::post('/job/{job}/cost/', 'Employee\CostItemController@store')->name('employee.costitem.store');
    Route::get('/job/{job}/cost/create', 'Employee\CostItemController@create')->name('employee.costitem.create');
    Route::delete('/job/cost/{cost}', 'Employee\CostItemController@destroy')->name('employee.costitem.destroy');
    
    //Quotation Section
    Route::post('/quotation', 'Employee\QuotationController@store')->name('employee.quotation.store');
    Route::get('/quotation', 'Employee\QuotationController@index')->name('employee.quotation.index');
    Route::get('/quotation/create', 'Employee\QuotationController@create')->name('employee.quotation.create');    
    Route::get('/quotation/json-companies/{id}','Employee\QuotationController@fetchCompanies');
    Route::get('/quotation/{quotation}', 'Employee\QuotationController@show')->name('employee.quotation.show');
    Route::get('/quotation/downloadPDF/{id}','Employee\QuotationController@downloadPDF');

    //PO Section
    Route::post('/po', 'Employee\POController@store')->name('employee.po.store');
    Route::get('/po', 'Employee\POController@index')->name('employee.po.index');
    Route::get('/po/prepare', 'Employee\POController@prepare')->name('employee.po.prepare');   
    Route::get('/po/{po}/edit', 'Employee\POController@edit')->name('employee.po.edit');

    //POItem Section
    Route::post('/poitem/create', 'Employee\POItemController@create')->name('employee.poitem.create');
    Route::get('/poitem/pending', 'Employee\POItemController@pendingList')->name('employee.poitem.pendinglist');
    Route::delete('/poitem/{poitem}', 'Employee\POItemController@destroy')->name('employee.poitem.destroy');

    //SubJob Section    
    Route::get('/job/{job}/subjob/create', 'Employee\SubJobController@create')->name('employee.subjob.create');
    Route::delete('/job/subjob/{subjob}', 'Employee\SubJobController@destroy')->name('employee.subjob.destroy');
    Route::post('/job/{job}/subjob', 'Employee\SubJobController@store')->name('employee.subjob.store');
    
    

        //EMPLOYEE USER SECTION
        Route::prefix('user')->group(function () {  
        
            //User Section
            Route::post('/user', 'Employee\User\UserController@store')->name('employee.user.user.store');
            Route::get('/user', 'Employee\User\UserController@index')->name('employee.user.user.index');
            Route::get('/user/create', 'Employee\User\UserController@create')->name('employee.user.user.create');
            Route::put('/user/{user}', 'Employee\User\UserController@update')->name('employee.user.user.update');
            Route::get('/user/{user}', 'Employee\User\UserController@show')->name('employee.user.user.show');
            Route::delete('/user/{user}', 'Employee\User\UserController@destroy')->name('employee.user.user.destroy');
            Route::get('/user/{user}/edit', 'Employee\User\UserController@edit')->name('employee.user.user.edit');
            Route::post('/user/{user}/assign', 'Employee\User\UserController@assignCompany')->name('employee.user.user.assign');
            Route::get('/user/json-companies/{id}','Employee\User\UserController@fetchCompanies');

            //User Company Section
            Route::post('/company', 'Employee\User\CompanyController@store')->name('employee.user.company.store');
            Route::get('/company', 'Employee\User\CompanyController@index')->name('employee.user.company.index');
            Route::get('/company/create', 'Employee\User\CompanyController@create')->name('employee.user.company.create');
            Route::put('/company/{user}', 'Employee\User\CompanyController@update')->name('employee.user.company.update');
            Route::get('/company/{user}', 'Employee\User\CompanyController@show')->name('employee.user.company.show');
            Route::delete('/company/{user}', 'Employee\User\CompanyController@destroy')->name('employee.user.company.destroy');
            Route::get('/company/{user}/edit', 'Employee\User\CompanyController@edit')->name('employee.user.company.edit');

            //Delivery Address Section
            Route::post('/delivery', 'Employee\User\DeliveryController@store')->name('employee.user.delivery.store');
            Route::get('/delivery', 'Employee\User\DeliveryController@index')->name('employee.user.delivery.index');
            Route::get('/delivery/create', 'Employee\User\DeliveryController@create')->name('employee.user.delivery.create');

        });

        //EMPLOYEE VENDOR SECTION
        Route::prefix('vendor')->group(function () {  

            Route::post('/vendor', 'Employee\Vendor\VendorController@store')->name('employee.vendor.vendor.store');
            Route::get('/vendor', 'Employee\Vendor\VendorController@index')->name('employee.vendor.vendor.index');
            Route::get('/vendor/create', 'Employee\Vendor\VendorController@create')->name('employee.vendor.vendor.create');
            Route::put('/vendor/{vendor}', 'Employee\Vendor\VendorController@update')->name('employee.vendor.vendor.update');
            Route::get('/vendor/{vendor}', 'Employee\Vendor\VendorController@show')->name('employee.vendor.vendor.show');
            Route::delete('/vendor/{vendor}', 'Employee\Vendor\VendorController@destroy')->name('employee.vendor.vendor.destroy');
            Route::get('/vendor/{vendor}/edit', 'Employee\Vendor\VendorController@edit')->name('employee.vendor.vendor.edit');

            Route::post('/company', 'Employee\Vendor\CompanyController@store')->name('employee.vendor.company.store');
            Route::get('/company', 'Employee\Vendor\CompanyController@index')->name('employee.vendor.company.index');
            Route::get('/company/create', 'Employee\Vendor\CompanyController@create')->name('employee.vendor.company.create');
            Route::put('/company/{vendor}', 'Employee\Vendor\CompanyController@update')->name('employee.vendor.company.update');
            Route::get('/company/{vendor}', 'Employee\Vendor\CompanyController@show')->name('employee.vendor.company.show');
            Route::delete('/company/{vendor}', 'Employee\Vendor\CompanyController@destroy')->name('employee.vendor.company.destroy');
            Route::get('/company/{vendor}/edit', 'Employee\Vendor\CompanyController@edit')->name('employee.vendor.company.edit');

        });
    
});
roerjo's avatar

Are the other delete routes working? That stack trace isn't very descriptive...is the Arguments part at the bottom saying that an empty string was passed as the method?

Arguments
""
zaster's avatar

@roerjo

Other deletes are working , this delete is the only issue.

Arguments part at the bottom saying that an empty string was passed as the method

Yes

munazzil's avatar

Can you check below command in your cmd and display result?

php artisan route:list

and get should be first in route list as like below.

Route::prefix('employee')->group(function () {    

  //More Routes

//POItem Section
Route::get('/poitem/pending', 'Employee\POItemController@pendingList')- 
>name('employee.poitem.pendinglist');
Route::post('/poitem/create', 'Employee\POItemController@create')->name('employee.poitem.create');
Route::delete('/poitem/{poitem}', 'Employee\POItemController@destroy')->name('employee.poitem.destroy');
    }
roerjo's avatar

@zaster As a debug, could try changing the route to:

Route::post('/poitem/{poitem}', 'Employee\POItemController@destroy')->name('employee.poitem.destroy');
zaster's avatar

@ROERJO -

    //POItem Section
    Route::post('/poitem/create', 'Employee\POItemController@create')->name('employee.poitem.create');
    Route::get('/poitem/pending', 'Employee\POItemController@pendingList')->name('employee.poitem.pendinglist');
    //Route::delete('/poitem/{poitem}', 'Employee\POItemController@destroy')->name('employee.poitem.destroy');
    Route::post('/poitem/{poitem}', 'Employee\POItemController@destroy')->name('employee.poitem.destroy');

same result

The browser url is appearing in this format now http://pk19.test/employee/poitem/5

Environment & details:
GET Data empty
POST Data
_token  
"wZVaD2F8XcrokdJjlA1XzlBxuucNQpiDnm1Qfpdq"
_method 
"DELETE"
roerjo's avatar

@zaster Is this exception being thrown after the item is deleted? Is it being thrown on the redirect back? Here:

 return back()->with('success','Information has been  deleted');
zaster's avatar

@roerjo

Even if the answer is not found for this, Thank you very much for all the support and effort given by you

zaster's avatar

@ROERJO -

return back()->with('success','Information has been  deleted');

Exception is not thrown and item is not been deleted

I have changed the destroy function as below

    public function destroy($id)
    {        
        $po_item = POItem::find($id);
        $po_item->delete();
        return back();
    }  

newSequence's avatar

If the item is being destroyed and you are attempting to then reload the page, is the error not occurring because you are attempting to load the page for a now invalid item id?

1 like
zaster's avatar

similar destroy method is used in other controllers and it works perfectly.

munazzil's avatar

Check with this because your passing in the form id and your using poitem

  Route::delete('/poitem/{id}', 'Employee\POItemController@destroy')->name('employee.poitem.destroy');

else simply use as like below and ignore that three routes

Route::resource('/poitem', 'Employee\POItemController');
zaster's avatar

@munazzil

    Route::delete('/poitem/{id}', 'Employee\POItemController@destroy')->name('employee.poitem.destroy');

Tried and still same error

munazzil's avatar

@ZASTER - Then check with resource route method and command other three routes.

Route::resource('/poitem', 'Employee\POItemController');
zaster's avatar

@munazzil

I don't think that's the way to move ahead

Anyway i have tried with tinker and records from po_items table can be deleted

munazzil's avatar

Can you provide the solution and Your model as well,can mark as solved.

for better pratice use as like this.

$po_item = POItem::findOrFail($id);
zaster's avatar

@munazzil

This issue is not solved. I only have used tinker and checked

something like this

$po_item = POItem::find(1);
$po_item->delete();

Snapey's avatar

Just checking, you know to clear the route cache?

Can you dd('something'); in your controller so that you can check it ever gets there.

The page that contains the delete form. Did you create it with a GET route or was it returned directly from a POST request?

munazzil's avatar

Problem with your form your given 'action' instead 'route' in this line i have changed.

inside the action={{}}.
  <div class="col-md-1">
  <form action="{{route('Employee\POItemController@destroy', $po_item->id)}}" method="post">
     {{csrf_field()}}
  <input name="_method" type="hidden" value="DELETE">
  <button class="btn btn-danger" type="submit">Delete</button>
    </form>
  </div>
Talinon's avatar

@munazzil - @zaster has already posted the rendered HTML

<form action="http://pk19.test/employee/poitem/2" method="post">

So how is route() supposed to now solve the problem?

roerjo's avatar
roerjo
Best Answer
Level 19

@zaster to ensure that it is not the redirect back() causing the issue, could you try instead redirecting to a specified route, like return redirect()->route('employee.poitem.pendinglist');?

Next

Please or to participate in this conversation.