Posting form in Laravel 4.1 and blade template - laravel

I'm having trouble posting forms using Laravel 4.1 with the blade template engine. The problem seems to be that the full URL including http:// is being included in the form action attribute. If I hard code the form open html manually and use a relative url, it works OK, however, when it has the full url, I am getting an exception.
routes.php
Route::any("/", 'HomeController#showWelcome');
HomeController.php
public function showWelcome()
{
echo($_SERVER['REQUEST_METHOD']);
return View::make('form');
}
Form opening tag in form.blade.php
{{ Form::open(["url" => "/","method" => "post","autocomplete" => "off"]) }}
{{ Form::label("username", "Username") }}
{{ Form::text("username", Input::old("username"), ["placeholder" => "john.smith"]) }}
{{ Form::label("password", "Password") }}
{{ Form::password("password", ["placeholder" => ""]) }}
{{ Form::submit("login") }}
{{ Form::close() }}
So if I go to my home dir / in the browser, I see the form that I have created. If I fill in the form details and click submit, I am simply taken to the same page - the request method is still GET as shown by echo($_SERVER['REQUEST_METHOD']);
I notice that the full
http://localhost/subdir/public/
url is used in the form markup. If I hardcode a form open tag in such as
<form action="/subdir/public/" method="post">
it works fine and $_SERVER['REQUEST_METHOD'] shows as post.
What am I doing wrong here?

You have created the route for the post?
example:
{{Form::open(["url"=>"/", "autocomplete"=>"off"])}} //No need to later add POST method
in Route.php
Route::post('/', 'YouController#postLogin');

you have not set up a route to handle the POST. You can do that in a couple of ways.
As pointed out above:
Route::post('/', 'HomeController#processLogin');
note that if you stick with your existing Route::any that the `Route::post needs to be before it as Laravel processes them in order (I believe).
You could also handle it in the Controller method showWelcome using:
if (Input::server("REQUEST_METHOD") == "POST") {
... stuff
}
I prefer the seperate routes method. I tend to avoid Route::any and in my login pages use a Route::get and a Route::post to handle the showing and processing of the form respectively.

Related

The PUT method is not supported for this route

I cannot submit form information through to store function in laravel controller. The form needs to create a - new - profile for a registered user.
I have even recreated the project, and redone the form - moving back into plain html as I suspect that the laravelCollective functions may be causing it but still the same error.
I have even rearranged the the form attributes as suggested in another post/thread.
I have even recreated the project, and redone the form - moving back into plain html as I suspect that the laravelCollective functions may be causing it but still the same error.
I have even rearranged the the form attributes as suggested in another post/thread.
The Form:
< form method="POST" enctype="multipart/form-data" action="{{ url('users/profile') }}" accept-charset="UTF-8" >
#csrf
...
// input fields here
...
< /form >
The Routes:
Route::resource('users/profile', 'ProfileController');
Route::get('/home', 'HomeController#index')->name('home');
Route::resource('users', 'UserController');
Route::post('users/profile', 'ProfileController#store')->name('profile.store');
The ProfileController#store function:
//some code omitted
public function store(Request $request)
{
$this->validate($request, [
'firstname'=>'required',
'lastname'=>'required',
...
'desc'=>'required'
]);
//handle file upload
if($request->hasFile('cover_image')) {
//Get file name with extension
$fileNameWithExt = $request->file('cover_image')->getClientOriginalName();
//Just file name
$fileName = pathinfo($fileNameWithExt, PATHINFO_FILENAME);
//Just Ext
$ext = $request->file('cover_image')->getClientOriginalExtension();
//FileName to Store
$fileNameToStore = $fileName.'_'.time().'_'.$ext;
//upload image
$path = $request->file('cover_image')->storeAs('public/users/'.auth()->user()->id.'cover_images/'.$request->input('firstname').'_'.$request->input('lastname').'_'.auth()->user()->id.'/',$fileNameToStore);
} else {
$fileNameToStore = 'noimage.jpg';
}
/*
*/
$profile = new Profile;
$profile->firstname = $request->input('firstname');
$profile->lastname = $request->input('lastname');
...
$profile->desc = $request->input('desc');
$profile->save();
return redirect('/users/profile');//->with('success','Profile Created');
}
The famous error:
Symfony \ Component \ HttpKernel \ Exception \
MethodNotAllowedHttpException The PUT method is not supported for this
route. Supported methods: GET, HEAD, POST.
Not sure what is causing the error, help appreciated.
If I understand it correctly this is for store function right? then you don't have to put #method('PUT') inside your form it should POST. The route of store in resource is POST.
this is your code that i deleted the #method('PUT')
< form method="POST" enctype="multipart/form-data" action="{{ url('users/profile') }}" accept-charset="UTF-8" >
#csrf ...
// input fields here ...
< /form >
The Routes: Route::resource('users/profile', 'ProfileController');
Route::get('/home', 'HomeController#index')->name('home');
Route::resource('users', 'UserController'); Route::post('users/profile', 'ProfileController#store')->name('profile.store');
and the PUT method is used for updating. When update in controller you need to pass id in your form that should look like this.
< form method="POST" enctype="multipart/form-data" action="{{ url('users/profile', $data->id) }}" accept-charset="UTF-8" >
#method('PUT')
#csrf ...
// input fields here ...
< /form >
I hope it helps!
you have problem in your routes file simply change your edit route to this route
Route::match(['put', 'patch'], 'the path you want /{id}','controllername#functionname');
you should notice that if you are new to laravel you should pass the id to this route as shown in this part {id} so that your edit function could display the previous data of it and also if you want to submit a the form it should have the put method and the html basic forms doesn't support that so you should find a way to submit it like using laravel collective or maybe put a hidden method in your form
if it doesn't work please give me a call
When using the Laravel resource method on a route, it makes things pretty specific in terms of what it is expecting. If you take a look at the chart on the manual, it is looking for a uri with the updating element id returned as part of the uri. The example looks like: /photos/{photo}. I'm not sure that this is how you've structured your html form.
You said you were using the LaravelCollective to get this working. This usually works fine, and has the massive advantage of easy form-model binding. But it helps to include the named route, which includes 'update' for the update resource. For example:
{!! Form::model($yourModel, array('route' => array('yourRoute.update',
$yourModel->id), 'method'=>'PUT', 'id'=>'Form'))!!}
I have not had an issue with the Collective using this method.

Laravel - route("resource.destroy") calls "resource.show"

This is the web.php
Route::group(['middleware' => 'auth'],
function () {
Route::get('letters/getRows', 'LetterController#getRows')->name('letters.getRows');
Route::get('letters/{letter}/A4', 'LetterController#A4')->name('letters.A4');
Route::get('letters/{letter}/A5', 'LetterController#A5')->name('letters.A5');
Route::resource('letters', 'LetterController');
}
);
I created a link as follow
"<a class='mx-2 h5' href='".route('letters.destroy', $entity->id)."'><i class='icon-remove-circle'></i></a>".
where the $entity->id is the id of the letter. The problem is, it links to show method not the destroy method. What can I do?
Using a form like this
{{ Form::open(array('route' => array('letters.destroy', $entity->id), 'method' => 'delete')) }}
<button type="submit" >Delete Account</button>
{{ Form::close() }}
may solve the problem but I want to use a tag not a form.
update
In the php artisan route:list, the url of destroy and show are the same
thanks
When you use the Route::resource method it will create, among others, a route to DESTROY a resource like this: /letters/:id/ and another route to EDIT the resource: /letters/:id, and one more to SHOW /letters/:id
They all look the same. However, the difference is in the HTTP method/verb used to reach each route.
If you look to the output if php artisan route:list, you will find the list of HTTP methods used. Something like:
GET|HEAD | letters/{letter} | letters.show
PUT|PATCH | letters/{letter} | letters.update
DELETE | letters/{letter} | letters.destroy
Therefore, to show a letter, you use a GET method, to edit a letter, use PUT method, and to destroy/delete, you use a DELETE method.
When you use an a tag, the browser will use the GET method, thus will reach the letters.show route. Html forms, can use POST or GET. Finally to use the DELETE http method, you need a form with hidden input named _method and the value="delete inside the form. Check the docs for more details.
There is also a note about this in LaravelCollective package documentations
Note: Since HTML forms only support POST and GET, PUT and DELETE methods will be spoofed by automatically adding a _method hidden field to your form.
Finally, if you must use an anchor tag <a>, you could use javascript to listen to the click event and submit a form with DELETE method.
Update to add an example:
You can find an example of using an anchor tag to submit the form, in the default app layout in the framework here
And this is a modified version to submit a delete request:
<a class="dropdown-item" href="#"
onclick="event.preventDefault();
document.getElementById('destroy-form').submit();">
{{ __('DELETE') }}
</a>
<form id="destroy-form" action="{{ route('letters.destroy', $entity) }}" method="POST" style="display: none;">
#method('DELETE')
#csrf
</form>
You cant. If you want to make a DELETE request you need to spoof it via a form (method POST, _method DELETE) or use Javascript.
Hyperlinks will cause new requests which will be GET requests. That is just how the web works.

custom validation, method not allowed on error

<form method="post" action="{{action('PLAYERController#update', $ply->reg_no)}}">
{{csrf_field()}}
Getting method not allowed exception on custom validation with false return. Tried mentioning PUT, PATCH and DELETE inside csrf field. Still, does not work.
UPDATE
using post for form method. Using method_field('POST'). not defining get method for the update function. If I go back from the error page back to the form page and press refresh, then the validation message is displayed as it should.
UPDATE 2
Validator::extend('check_sold_amount', function($attribute, $value, $parameters, $validator) {
if(($value%5000)==0)
{
return true;
}
return false;
});
}
UPDATE 3
Controller code
public function update(Request $request, $reg_no)
{
//
$this->validate($request, [
'sold_amount' => 'required|check_sold_amount',
'sold_to_team'=>'required'
]);
$ply = Player::find($reg_no);
$ply->sold_amount = $request->get('sold_amount');
$ply->sold_to_team = $request->get('sold_to_team');
$team_name=$ply->sold_to_team;
$team=Team::find($team_name);
if($ply->category=='indian')
{
$team->indian_players=$team->indian_players+1;
}
else {
$team->foreign_players=$team->foreign_players+1;
}
$team->balance=$team->balance-$ply->sold_amount;
$ply->save();
$team->save();
//return view('player.index');
}
Method not allowed means you do not have a route set up for the request that happened. There are 2 possibilities:
The route for the form submission is not set up
The code you have shown us does not include any method_field(...), so it looks like you are doing a normal POST. So you need a corresponding POST route like:
Route::post('/some/path', 'PLAYERController#update');
The route for the failed validation response is not set up
I'm guessing this is the problem. Say you are on pageX, and you landed here via a POST. You have a post route set up, so that you can land on this page OK. Now from this page, you submit the form you have shown us, but validation fails. When that happens, Laravel does a GET redirect back to pageX. But you have no GET route set up for pageX, so you'll get a Method not allowed.
Along with your POST route for the current page, you need a GET route to handle failed validations.
Also, you say Tried mentioning PUT, PATCH and DELETE inside csrf field - as others pointed out, you should use method_field() to spoof form methods, eg:
<form ...>
{{ csrf_field() }}
{{ method_field('PATCH') }}
Laravel form method spoofing docs
UPDATE
Based on your comments, I think it is actually your initial POST that is failing. Checking your code again, I think your action() syntax is incorrect.
According to the docs, if the method specified in the action() helper takes parameters, they must be specified as an array:
action="{{ action('PLAYERController#update', ['reg_no' => $ply->reg_no]) }}"
If your update route using patch method (example Route::patch('.....');) then add this {{ method_field('PATCH') }} below {{csrf_field()}} in your update form
UPDATE
If you are not using PATCH method for the update route, try this :
Route::patch('player/update/{reg_no}', 'PLAYERController#update')->name('plyupdate');
and then in the form you can do like below :
<form method="POST" action="{{route('plyupdate', $ply->reg_no)}}">
{{csrf_field()}}
{{ method_field('PATCH') }}
//Necessary input fields and the submit button here
</form>
This way always works fine for me. If it still didn't work, maybe there's something wrong in your update method in the controller
UPDATE
Untested, in your update method try this :
public function update(Request $request, $reg_no) {
$input = $request->all();
$ply = Player::find($reg_no);
$validate = Validator::make($input, [
'sold_amount' => 'required|check_sold_amount',
'sold_to_team'=>'required'
]);
if ($validate->fails()) {
return back()->withErrors($validate)->withInput();
}
$ply->sold_amount = $request->get('sold_amount');
$ply->sold_to_team = $request->get('sold_to_team');
$team_name=$ply->sold_to_team;
$team=Team::find($team_name);
if($ply->category=='indian') {
$team->indian_players=$team->indian_players+1;
}
else {
$team->foreign_players=$team->foreign_players+1;
}
$team->balance=$team->balance-$ply->sold_amount;
$ply->save();
$team->save();
return view('player.index');
}
Don't to forget to add use Validator; namespace
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* Show the profile for the given user.
........................
Did you reference a validation request controller?
Hope this helps :)

can I use route() to make a DELETE request in laravel

I'm using laravel and trying to delete something. Is it possible to specify the DELETE method on laravel's route()??
e.g
route('dashboard-delete-user', ['id' => $use->id, 'method'=> 'delete'])
or something like that??
EDIT:
What I meant was could I specify that in a link or a button in my blade template. Similar to this:
href="{{ route('dashboard-delete-user') }}
Yes, you can do this:
Route::delete($uri, $callback);
https://laravel.com/docs/master/routing#basic-routing
Update
If for some reason you want to use route only (without a controller), you can use closure, something like:
Route::get('delete-user/{id}', function ($id) {
App\User::destroy($id);
return 'User '.$id.' deleted';
});
No or at least I haven't figure out how to.
The only way for this to work out of the box would be to build a form to handle it. At the very minimum, you would need...
<form action="{{ route('dashboard-delete-user') }}" method="POST">
{{ method_field('DELETE') }}
{{ csrf_field() }}
<button type="submit" value="submit">Submit</button>
</form>
Or you can just create the get route which you are trying to link to and have it handle the logic. It doesn't need to be a route which only respondes to delete requests to delete a resource.
Yes you can, using a URL helper. https://laravel.com/docs/5.2/helpers#urls
There are several options to choose from.

Laravel: delete photo by photo id

I'm trying to delete a photo by it's id, but the routes do not work and I receive a MethodNotAllowedHttpException. What I do:
First I create a form (in my blade template):
{{ Form::open(array("action" => array("cms/albums/destroyphoto", $photo['id']), "method" => "DELETE")) }}
<button type="submit">Delete</button>
{{ Form::close() }}
Then i create my route:
Route::post('cms/albums/destroyphoto/{id}', 'AlbumsController#destroyphoto');
And create my function in the Albumscontroller:
public function destroyphoto($id)
{
dd('Welcome photo');
}
Any suggestions where the routing goes wrong?
Thanks in advance.
Ps. I did composer dump-autoload
When you open your form using "action" you should pass the controller class and action name. You also don't need to specify the method since you're using Route::post
Like this:
{{ Form::open(array("action" => array("AlbumsController#destroyphoto", $photo['id']))) }}
More information

Resources