Laravel resource routing - update throws "method not allowed" error - php

I have the following resource route:
Route::resource('pools', 'PoolsController');
I also have an edit form which should post to the controller's "update" method, set up like this:
{{ Form::open(array('route' => ['pools.update', $pool['id']])) }}
When I submit the form, it opens www.domain.com/pools/6 (6 being $pool['id'] above). However, instead of running the code in the update() method, it throws an error:
Symfony \ Component \ HttpKernel \ Exception \ MethodNotAllowedHttpException
Now, I've found Laravel's error reporting very unhelpful so far, and this is no exception. The error description is vague at best and does nothing to help me troubleshoot the issue.
I was under the impression that the update method should receive post data automatically when using resourceful routing. It has also worked in some examples before, using the same syntax.
So, can anyone tell me what might be going on here?

to run the code in the update method, you must spoof a PUT request. look here: Form Method Spoofing

Related

Method not allowed - redirect using incorrect method

I have been working on a simple Laravel Inertia Vue3 application. It has one resource route.
Route::resource('contact', \App\Http\Controllers\ContactController::class);
This provides the named routes contact.index .store .create .show .update .destroy and .edit
Nice and simple so far.
I have a useForm form variable in my Vue component with some assigned variables
let form = useForm({ ... });
I have a submit method in the same component
let submit = () => {
if(props.edit) {
form.patch(`/contact/${props.contact.id}`);
} else {
form.post(`/contact`);
}
}
Again nothing complex. The post method fires off correctly and redirects
Contact::query()->create($request->all());
return redirect()->to(route('contact.index'));
For full disclosure of the update method, please see below:
public function update(Request $request, Contact $contact): \Illuminate\Http\RedirectResponse
{
$contact->fill($request->all())->save();
return redirect()->to(route('contact.show', ['contact' => $contact]));
}
This works in the same way as store. Simple and then redirects... but it doesn't.
What happens is that it runs the patch and then calls redirect
The redirect carries the patch method through ending up with a 405 if I use the index route (declared as get). If I use back() I get the same thing. If I use the show route, it redirects in a loop because the patch route uses the same URL /contact/{contact}
I have built Laravel applications for the last 5 years and have not had an issue like this before when using a named route. Have I missed something basic? If not its possibly a configuration issue although I am not sure what.
I am running Laravel 9.19 with webpack manually installed as its been changed to Vite on the current release. I have no Vue errors or warnings and no Laravel logs.
there is a difference between PUT and PATCH requests on laravel-level.
Please run php artisan route:list - and see which one is used in your case, There is a big chance that you using PUT, not patch :)
So good ol' Laravel got me again.
Alexander Dyriavin got me on the right course with his answer about put and patch, however, it wasn't really the solution.
The solution:
form.transform((data) => ({
...data,
_method: 'PUT' //spoof added to request
})).post(`/contact/${props.contact.id}`); //sent as a post instead
The Laravel docs allow you to spoof methods https://laravel.com/docs/5.0/routing#method-spoofing by posting them with a _method field.
Simply put, a patch or put request would have always failed with a redirect from Laravel. In the past I would have used them with Axios and handled a JSON response directly.
This time I really am answering my own question.
I was a total idiot and missed a step when setting up inertia js. I was attempting to retrieve errors with the useform method and what happened was I received nothing.
So I though I would double check the docs.
Turns out I missed adding this middleware to the web middleware group in the kernel!
\App\Http\Middleware\HandleInertiaRequests::class,
I can now use the .patch method I had before and no need for any additional code

Twig reports "An exception has been thrown during the rendering of a template" in Laravel

I am getting this error in Laravel:
Twig \ Error \ RuntimeError An exception has been thrown during the
rendering of a template ("Route [shortname.shortname_list] not
defined.") in "common.sidebar.vendor.twig" at line 154.
I already checked my sidebar.twig, route list and controller, it seems like fine.
What does this error mean, and what is a possible solution?
This error means that a route with the name shortname.shortname_list isn't defined in your route configuration.
You need to ensure that you have a route with the name shortname.shortname_list to be able to generate a URL for it in twig.
Route::get('route-path', ['uses' => 'Controller#method'])
->name('shortname.shortname_list');

Laravel returns MethodNotAllowedHttpException on routing does not exist

I created a route for buy an item in laravel 5.7
Route::post('/buy/item', "userController#buy_item")->name('buy_item_form');
Everything works fine but when I refresh the page(replace to GET Request) I got an
MethodNotAllowedHttpException.
The GET route not exist, Its must return an 404 error.
I dont understant why its return me this exception.
You are using a post, with post you have a #csrf token. when you click on refresh, you are doing a GET method instead of a post and for hence you get the method not allow exception. If you are not sending data you can change it to a get [Route::get] method.
If you want to accept the 2 methods [post,get] to have a better experience and manage the possible errors. You can accept the 2 methods on the route like:
Route::match(array('GET','POST'),'/buy/item', 'userController#buy_item')->name('buy_item_form');
And on the controller, define what to do base on the method.
if (Request::isMethod('get')){
// redirect user
}
if (Request::isMethod('post')){
// do logic for post method
}

404 issue with Laravel route

I am very confused as to why this is happening but here is the issue guys. Basically I am building an app using laravel4 I want to go to this URL
http://app.tld/books
However I get this error every time:
404: The requested URL /books was not found on this server.
However in my routes.php file I have the route defined:
Route::get('/books', 'BookController#index');
I also have a view and relevent method in Controller:
public function index(){
$books = Book::all();
return View::make('book.index')->with('books', $books);
}
From the comments we gather that it was an Apache issue, not a Laravel issue (mod_rewrite wasn't enabled -- kudos to #watcher), and I'm glad you sorted it out.
For future reference, it seemed likely to be an Apache issue because Laravel throws PHP exceptions on undefined routes, namely a Symfony \ Component \ HttpKernel \ Exception \ NotFoundHttpException. If you have debug set to true you'll get a neatly styled stack trace with code highlighting and server/request data, if not you'll get a neatly styled "Whoops, looks like something went wrong." message. If, on the other hand, you get a white screen with Times New Roman messages like "404: The requested URL /books was not found on this server.", Laravel isn't even starting up.
As the comments on your question show, there are many other clues which will tell you that it's not your Laravel routes, though from the code you posted and even the title of the question, you seemed to had narrowed it down to routes, which probably had you looking in the wrong place for a while.

laravel 4 route not found - defaults to show method

I've had this working but now a route is no longer found and I can't see why.
In a javascript function I am making an ajax post to the function with this url:
url: '/customers/storeajax',
In my routes.php file I have the following routes:
Route::post('customers/storeajax', array('as'=>'storeajax', 'uses' => 'CustomersController#storeAjax'));
Route::post('customers/updateajax/{id}', array('as'=>'updateajax','uses' => 'CustomersController#updateAjax'));
Route::resource('customers', 'CustomersController');
Now when I try to POST to the storeajax route I get a ModelNotFoundException which to me means the route could not be found so it defaults to the default customers controller show method - in the error log I can see the following entry:
#1 [internal function]: CustomersController->show('storeajax')
confirming its treating the storeajax as a parameter.
I've placed my additional routes above the default resource route
I've had this working before I can't see where I've gone wrong.
In addition these routes are placed in a group:
Route::group(array('before' => 'sentryAuth'), function () {}
which simply ensures user is logged on. To test though I've removed outside the group and at the top of the file but still they don't work.
The url in my browser is coming up correctly as: http://greenfees.loc/customers/storeajax (which I can see in firebug console
I'm using POST as the ajax method - just to confirm
Can anyone see why this route doesn't work and what I've missed?
Update:
Here's the method inside the controller:
public function storeAjax()
{
$input = Input::all();
$validation = Validator::make($input, Customer::$rules);
if ($validation->passes())
{
$customer = $this->customer->create($input);
return $customer;
}
return Redirect::route('customers.create')->withInput()
->withErrors(validation)
->with('message', 'There were validation errors.');
}
I'm 99% certain though that my route is not reaching this method (i've tested with a vardump inside the method) and the issue relates to my route customer/storeajax cannot be found.
What I think is happening is as customer/storeajax is not found in the list of routes starting with customer it is then defaulting to the resource route that appears on the list and thinks this is a restful request and translating it as customer route which defualts to the show method and using the storeajax as the parameter which then throws the error modelnotfoundexception because it cant find a customer with an id of 'storeajax'
This is evidence by the log detailing a call to the show method as above.
So for some reason my route for '/customers/storeajax' cannot be found even though it appears to be valid and appears before the customers resource. The modelnotfoundexception is a red herring as the cause is because of the routes defaulting to the resource constroller of customers when it cant find a route.
A route not being found raises a NotFoundHttpException.
If you are getting a ModelNotFoundException is because your route is firing and your logic is trying to find a Model, wich it can't somehow, and it is raising a not found error.
Are you using FindOrFail()? This is an example of method that raises this exception. BelongsToMany() is another one that might raise it.
I solved this by renaming the method in the controller to 'newAjax' and also updating the route to:
Route::post('customers/new', array('as'=>'newajax','uses' => 'CustomersController#newAjax'));
the terms store I assume is used by the system (restful?) and creating unexpected behaviour. I tested it in a number of other functions in my controller - adding the term store as a prefix to the method then updating the route and each time it failed.
Something learned.

Categories