Why submitting form with PUT method I got GET request? - laravel-5

In my laravel 5.7 app I make form for updating of data, like:
<section class="card-body">
<h4 class="card-title">Edit vote</h4>
<form method="PUT" action="{{ url('/admin/votes/update/'.$vote->id) }}" accept-charset="UTF-8" id="form_vote_edit" class="form-horizontal"
enctype="multipart/form-data">
{!! csrf_field() !!}
<ul class="nav nav-pills mb-3" id="pills-tab" role="tablist">
with routes dined in routes/web.php:
Route::group(['middleware' => ['auth', 'isVerified', 'CheckUserStatus'], 'prefix' => 'admin', 'as' => 'admin.'], function () {
...
Route::put('/votes/update/{vote_id}', 'Admin\VotesController#update');
but submitting the form I got request with error:
Request URL: http://local-votes.com/admin/votes/update/22?_token=0CEQg05W4jLWtpF3xB6BGSdz1icwysiDOStLVgHv&id=22&name=gg...
Request Method: GET
Status Code: 405 Method Not Allowed
Why GET request, what is wrong in my form ?
Thanks!

HTML Forms only support GET and POST.
From the docs:
Since HTML forms can't make PUT, PATCH, or DELETE requests, you will
need to add a hidden _method field to spoof these HTTP verbs.
You can use the method_field helper or the #method blade directive to add the hidden input.
<form action="/foo/bar" method="POST">
#method('PUT')
...
</form>
or
<form action="/foo/bar" method="POST">
{{ method_field('PUT') }}
...
</form>

Related

I find this error: Illuminate\Routing\Exceptions\UrlGenerationException Missing required parameters for [Route: Product.update]

Controller:
public function update(Request $request, Product $product)
{
$request->validate(['name'=>'required',
'price'=>'required'
]);
$product->update($request->all());
}
In the view:
<form action="{{route('Product.update',$product)}}" method="GET">
Route:
Route::resource('Product', 'ProductController');
Parameter Request will come from the data of form
Change this line:
<form action="{{route('Product.update',$product)}}" method="GET">
to
<form action="{{ route('Product.update', ['product' => $product]) }}" method="POST">
The default Route::resource HTTP method for update action is 'patch' and 'put'.
So in view, you may pass 'post' as method instead of 'GET'.
Then you should write {{ method_field('PUT') }} and a hidden input after your form tag as below :
<form method="POST" action={{ route('product.update' , $product) }}>
#csrf
{{ method_field('PUT') }}
<input type="hidden" name="_method" value="PUT">
</form>
Looking through the Laravel docs, I think for the view you need to do POST instead of GET. You might also need to spoof the form method with #method('PUT').

the PUT method does not send messages

if necessary, I will also put the controller in check although it seems to
me that something is wrong with the method because on the output it shows me a "no message" error and nothing more
is on a piece of my view and the PUT method
{!! Form::model($cattle_inventory, array('route'=>
['cattle_inventories.update',$cattle_inventory->id,'method'=>'PUT']))!!}
<div class="form-group">
{!! Form::label('cow_name','Podaj NazwÄ™ krowy') !!}
{!! Form::text('cow_name',null, ['class'=>'form-control']) !!}
</div>
Route
Route::resource('cattle_inventories','Cattle_inventoryController')->middleware('verified');
The documentation states:
HTML forms do not support PUT, PATCH or DELETE actions. So, when defining PUT, PATCH or DELETE routes that are called from an HTML form, you will need to add a hidden _method field to the form. The value sent with the _method field will be used as the HTTP request method:
<form action="/foo/bar" method="POST">
#method('PUT')
#csrf
</form>
Hence you need to adjust your form as such. #method('PUT') simply generates the following HTML:
<input type="hidden" name="_method" value="PUT">
You can try this with Laravel collective
{!! Form::open(['route'=>['your.route', $id]]) !!}
// laravel <=5.5
{!! Form::hidden('_method', 'PUT') !!} //or {{ method_field('PUT') }}
//laravel >=5.6
#method('PUT')
{!! Form::close() !!}
Laravel collective Form model binding
{{ Form::model($cattle_inventory, ['route' => ['cattle_inventories.update', $cattle_inventory->id]]) }}

Laravel forcing POST routes into GET

Router:
Route::post('/submit/{id}', function() {
return 'Hello World';
});
HTML:
<form method="POST" action="/submit/{{$id}}">
The above changes the URL to http://127.0.0.1:8000/submit/$id and returns
Page has Expired Due to Inactivity.
It looks like Laravel is trying to force the POST into a GET.
This problem is because you forget to put the CSRF token field into the form.
Try with:
Option 1
<form method="POST" action="{{url('submit', [$id])}}">
{{ csrf_field() }}
<button type="submit">Submit</button>
</form>
Option 2
<form method="POST" action="{{url('submit')}}/{{$id}}">
#csrf
<button type="submit">Submit</button>
</form>
For more info see this link

Laravel delete method not working with DELETE verb

In my routes file, I have
Route::delete('events/{events}', ['as' => 'events_delete', 'uses' => 'Admin\EventsController#destroy'] );
In my view file I have
<em class="fa fa-trash"></em>
This does not work. When I change the route to
Route::get('events/{events}', ['as' => 'events_delete', 'uses' => 'Admin\EventsController#destroy'] );
it does work. However I don't like the idea of using a GET verb to delete items instead of the DELETE verb. It feels like a trick...
How can I change the form code to make sure it sends a DELETE verb?
Solution 1 (from TheFallen): with DELETE VERB in routes file
<form action="{!! route('events_delete', ['id' => $event->id ]) !!}" method="POST">
{{ method_field('DELETE') }}
{{ csrf_field() }}
<button class="btn btn-danger btn-sm" type="submit"><em class="fa fa-trash"></em></button>
</form>
Solution 2: with GET VERB in routes file
<em class="fa fa-trash"></em>
You have to make a delete request to use the route this way, which you can do with a form, otherwise with the anchor you're making a get request.
If you already don't have the laravelcollective/html package install it from composer to use the forms facade. Then you can make the request like this:
{!! Form::open(['method' => 'DELETE', 'route' => $yourRoute]) !!}
{!! Form::submit('Delete') !!}
{!! Form::close() !!}
EDIT:
Without the forms facade:
<form action="{{ $yourRoute }}" method="POST">
{{ method_field('DELETE') }}
{{ csrf_field() }}
<button class="btn btn-danger btn-sm" type="submit"><em class="fa fa-trash"></em></button>
</form>
That will produce a GET request, therefore it will not match Route::delete
HTML forms do not support PUT, PATCH or DELETE actions. So, when defining PUT, PATCH or DELETE routes that are called from an HTML form, you will need to add a hidden _method field to the form.
Refer: https://laravel.com/docs/master/routing#form-method-spoofing
To call the delete route, you have to implement using jquery
<a eventid="{{$event->id}}" href="#" type="button" class="btn btn-sm btn-danger"><em class="fa fa-trash"></em></a>
$(document).on("click",".anchorclass",function(e){
e.preventDefault();
if(!confirm("Are you sure?")) return;
$.ajax({
type: "DELETE",
url: 'events/'+$(this).attr("eventid"),
success: function(data) {
//Process results
}
});
});

Laravel href with POST

I'm trying to pass some data to my controller with an action href. I don't know why, but laravel passes the data with GET method, but instead of GET I need a POST. I don't really understand why laravel does that and coulnd't find an answer. I did that multiple times and my syntax seems to be correct. Can somebody have a look over it?
Blade:
<td>
#foreach($products as $product)
<a href="{{ action('ProductsController#delete', $product->id ) }}">
<span class="glyphicon glyphicon-trash"></span></a>
{{ $product->name }},
#endforeach
</td>
My Route:
Route::post('delete', ['as' => 'delete', 'uses' => 'ProductController#delete']);
In my Controller is just a:
public function delete()
{
return 'hello'; // just testing if it works
}
Error:
MethodNotAllowedHttpException in RouteCollection.php line 219....
I know it's a get method, cause if I'm trying to pass the data to my controller, my URL looks like this:
blabla.../products/delete?10
Is anything wrong with my syntax? I can't really see why it uses the get method.
I also tried a: data-method="post" insite of my <a> tag but this haven't worked either.
Thanks for taking time.
When you make a link with an anchor like <a href=example.com> your method will always be GET. This is like opening a URL in your browser, you make a GET request.
You should use a form to make that POST request to the delete method of the controller. Assuming you have the Illuminate HTML package for HTML and forms, you could do this:
{!! Form::open(['method' => 'DELETE', 'route' => $route]) !!}
{!! Form::submit('delete', ['onclick' => 'return confirm("Are you sure?");']) !!}
{!! Form::close() !!}
EDIT:
With a button tag:
{!! Form::open(['method' => 'DELETE', 'route' => $route]) !!}
<button type="submit"><i class="glyphicon glyphicon-remove"></i>Delete</button>
{!! Form::close() !!}
Here's your problem:
<a href="{{ action('ProductsController#delete', $product->id ) }}">
Anchor tags are always submitted over GET. It's a HTTP built in and is not Laravel specific.
POST is used when a form is submitted that specifies the POST HTTP Verb or the HTTP method is invoked by an AJAX request that specifies POST as the HTTP Verb.
Instead consider a submit type button in a form that submits what you need.
<td>
#foreach($products as $product)
<form method="POST" action="{{ route('delete') }}">
<input type="hidden" name="product_id" value="{{ $product->id }}">
{!! csrf_field() !!}
<button type="submit" class="btn">
<span class="glyphicon glyphicon-trash"></span>
</button>
</form>
{{ $product->name }},
#endforeach
</td>
And then in your controller:
public function delete()
{
// 'Die Dump' all of the input from the form / request
dd( request()->input()->all() );
// 'Die Dump' the specific input from the form
dd( request()->input('product_id') );
}
You will begin to see how GET and POST requests differ in sending of key/value pairs.
For more information:
http://www.tutorialspoint.com/http/http_methods.htm
Best for laravel 7. First define the form with given form id.
#auth
<form id="logout-form" action="{{ route('logout') }}" method="POST"
style="display: none;">
#csrf
</form>
#endauth
Then you can use the anchor tag for logout operation.In background,javascript working.Wherever the logout was fire then action to given form method of post method and logout route was working.
<a class="nav-link dropdown-toggle text-muted waves-effect waves-dark"
href="{{ route('logout') }}" onclick="event.preventDefault();document.getElementById('logout-form').submit();"
id="2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="mdi mdi-logout"></i>
</a>
Most benefit is the form was not loaded unnecesory.If the user was
logged in so far its load otherwise not
Laravel 7
By jQuery:
<form id="form" action="{{route('route_name')}}" method="POST">#csrf</form>
By JS:
<form id="form" action="{{route('route_name')}}" method="POST">#csrf</form>

Resources