I am creating an API for Laravel. I use the PUT method for updating data.
I send data with Postman using the PUT method. In my controller, I got an empty array. How to access the passed data?
In my route, I have:
Route::put('vehicletypes/{id}','API\VehicletypeController#update');
In my controller:
public function update(Request $request, $id){
print_r($request->all()); exit;
}
How to get the data passed in PUT method?
You are getting empty response because PHP have some security restrictions against PUT. But Laravel have a workaround for this.
So, to solve this you have to send a POST request from Postman instead, with a POST param _method with value PUT. And that should work.
Laravel cheats because html forms only support GET and POST, but it does understand a real PUT/PATCH request.
The problem looks like lies in Symfony it can't parse the data if it's multipart/form-data, as an alternative try using x-www-form-urlencoded content disposition.
public function putUpdate(Request $request, $id){
print_r($request->all()); exit;
}
And change route too,
Route::put('vehicletypes/{id}','API\VehicletypeController#putUpdate');
Checked "x-www-form-urlencoded" instead of "form-data" under body tab in the Postman, the put methood will work as well...
Why nobody is giving clear explanation
at first put method field of
{{method_field('put')}}
as your router uri is that is displayed using command
php artisan router:list
of update method is put/patch so first add
{{method_field('put')}}
and field in your form should be the same
<form action="{{route('posts.update',$post->id)}}" method="post">
after adding the csrf_toke form will be working. and final shape would be as below of form.
<form action="{{route('posts.update',$post->id)}}" method="post" >
{{method_field('put')}}
<input type="hidden" name="_token" value="{{csrf_token()}}">
<!-- Name input-->
<div class="form-group">
<label class="col-md-3 control-label" for="name">Title</label>
<div class="col-md-9">
<input id="name" name="title" type="text" value="{{$post->title}}" class="form-control">
</div>
</div>
<!-- Message body -->
<div class="form-group">
<label class="col-md-3 control-label" for="body">
Body</label><br>
<div class="col-md-9">
<textarea class="form-control" id="message" name="body" rows="5">
{{$post->body}}
</textarea>
</div>
</div>
<!-- Form actions -->
<div class="form-group">
<div class="col-md-9 text-right col-md-offset-3">
<button type="submit" class="btn btn-success btn-lg">Update</button>
Cancel
</div>
</div>
</form>
Following link will resolve the issue to get the request form data plus the images.
If you are working on Laravel, you can easily parse and bind the form params in the \Illuminate\Http\Request Instance
Simply just get the ParseInputStream Class from the link below:
Class ParseInputStream.php
Create another Validation Rule Class in Laravel optional but not required,
class NoteUpdateRequest extends Request {
public function all($keys = null)
{
if(strtolower($this->getMethod())=='put' && preg_match('/multipart\/form-data/', $this->headers->get('Content-Type')) or
preg_match('/multipart\/form-data/', $this->headers->get('content-type')))
{
$result = [];
new ParseInputStream($result);
$result = array_merge($result, $this->route()->parameters());
$this->request->add($result);
}
return parent::all($keys);
}
public function rules()
{
dd($this->all());
return [
'noteId' => 'required|integer|exists:notes,id',
'title' => 'required|string|max:200',
'note' => 'required|string|min:10|max:2000'
];
}
}
I hope it resolved what you want to achieve, using PUT or PATCH method along with Form Params
As mentioned, this isn't a laravel (or symfony, or any other framework) issue, it's a limitation of PHP.
That said, I managed to find this PECL extension. I'm not very familiar with pecl, and couldn't seem to get it working using pear. but I'm using CentOS and Remi PHP which has a yum package.
I believe there are other packages in various flavours of linux and I'm sure anybody with more knowledge of pear/pecl/general php extensions could get it running on windows or mac with no issue.
I ran yum install php-pecl-apfd and it literally fixed the issue straight away (well I had to restart my docker containers but that was a given).
That is, request->all() and files->get() started working again with PATCH and PUT requests using multipart/form-data.
Ergo, I managed to get my api playing nicely with my front-end without adding any quirks (that would need to be relayed to anybody developing front-end solutions) or breaking RESTful conventions.
Related
I'm learning Laravel. The current stable version is, as far as I'm aware, 5.8. I'm following tutorials and really liking the framework, but it gets a bit troublesome when these tutorials get to the point where they introduce how forms are incorporated. All of those tutorials use LaravelCollective forms, which is no longer working as of 5.8 and it is an abandoned project so I'd prefer not to use it anyway.
But this leaves me confused as to what the best practices are for using forms with Laravel. I've had some goes at creating forms, but... most of it is just HTML with hardly any Laravel "in there", if that makes sense. The only Laravel bit here is the form action, where it points to the store function in the TodosController. See below, for a file called create.blade.php.
#extends('layouts.app')
#section('content')
<h1>Create Todo</h1>
<form action="{{action('TodosController#store')}}" method="post">
#csrf
<div class="form-group">
<label for="text">Text</label>
<input type="text" name="text" class="form-control" placeholder="Enter title"/>
</div>
<div class="form-group">
<label for="body">Body</label>
<textarea class="form-control" name="body" id="body" rows="10" placeholder="Enter details"></textarea>
</div>
<div class="form-group">
<label for="due">Due date</label>
<input type="text" name="due" class="form-control" placeholder="Enter due date"/>
</div>
<input type="submit" value="Submit" class="btn btn-primary">
</form>
#endsection
This works fine, but I just feel like I'm not utilising blade properly here at all. Any pointers would be greatly appreciated.
Actually, you're using more laravel there than just the form action. The #csrf stands for Cross-site request forgery and it's the laravel way to protect you against that, as said in the docs:
Laravel automatically generates a CSRF "token" for each active user session managed by the application. This token is used to verify that the authenticated user is the one actually making the requests to the application.
Anytime you define a HTML form in your application, you should include a hidden CSRF token field in the form so that the CSRF protection middleware can validate the request. You may use the #csrf Blade directive to generate the token field:
When you have a PUT, PATCH OR DELETE form you should use the blade directive #method to inform wich action laravel should use:
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:
You can achieve that, simply using:
<form action="/foo/bar" method="POST">
#method('PUT')
#csrf
</form>
Besides that, i think you're using laravel/blade just fine. Make sure you read the docs for more info.
Good luck!
What you have is a good point to start from, however another good place to take a look at is the boilerplate registration form (this is not from the official Laravel project page because the boilerplates are optionally introduced and are not in the official repo by default).
There are a few improvements you can do based on this:
<div class="form-group">
<label for="text">{{__('Text')}}</label>
<input type="text" name="text" class="form-control{{ $errors->has('text') ? ' is-invalid' : '' }}" value="{{ old('text') }}"placeholder="Enter title"/>
</div>
The extras:
__('Text') will automatically translate Text based on the selected locale and available language assets.
{{ $errors->has('text') ? ' is-invalid' : '' }} will "decorate" the field with the bootstrap-4 error style if serverside validation failed (and therefore passed the $errors variable to the view)
{{ old('text') }} will pre-fill the input with the value that was previously filled in case the form failed validation and the user was redirected back to the same page.
This will help improve the user experience, however keep in mind these are all server-side tools (because Laravel is a server-side framework) so it's probably a better user experience to also add client-side checks and validation.
I am making a simple task app in laravel to cement the basics into my head. I have a page set-up with a form to make a task then submit it to the database, then redirect back to the home page. when I click submit it gives me this screen:
The page has expired due to inactivity.
Please refresh and try again.
my have the project on GitHub here: https://github.com/fullstackfox16/laravel-task
any help would be greatly appreciated!
I found that you forgot to add csrf_token field to your form.
<form method="POST" action="/posts">
<input type="hidden" name="_token" value="{{ csrf_token() }}"> <!-- THIS LINE -->
<div class="field">
<label class="label">Task</label>
<div class="control">
<textarea class="textarea" placeholder="Textarea" name="body"></textarea>
</div>
</div>
<div class="field is-grouped">
<div class="control">
<button class="button is-primary">Add Task</button>
</div>
</div>
</form>
And if the problem persists, clean your browser cache and try again.
Can you more specific in your question. In general when using HTML form you can use redirect back after your request is handle with message bag to show a message feedback to your user, if you have white screen or something else abnormal make sure you don't have error syntax
There are two ways you can work this out:
One, is adding the csrf_field() in your form. nice and easy.
Or
you can omit that route form the VerifyCsrfToken middlaware.
app/Http/Middleware/VerifyCsrfToken.php
protected $except = [
'your/route'
];
I am a beginner PHP developer, i was implementing CRUD with Laravel 5.4 framework, and all works fine so far.
But i was then trying to make this code functional in website and mobile as well, so i get to know web services and it's protocols like Rest,Soap, i was successfully managed to work with them and build small size scripts for self learning and things get better.
When i try to apply what i have learned on my CRUD i stuck , there is no links to structure my code over just routes and a with api.php,web.php files , i don't know where to build my server or client scripts and how to link them in laravel even though i managed to implement this in native php , but things a little bit confusing for me in laravel i surfed the internet and found nothing useful for me actually ..
i will provide simple of my CRUD code on the (Create New User Function) .and wish if any one could help me or put me on track to start using this technique with different projects.
My Controller
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\user;
class AddController extends Controller
{
public function create(){ //create new user page
return view('add.create');
}
public function store(){ //store new user added by a clint
$this->validate(request(), [ //validation for request records
'name' => 'required',
'email' => 'required',
'password' => 'required|min:8',
'password_confirmation' => 'required|same:password'
]);
$user = User::create([ //create new user with the request records
'name' => request('name'),
'email' => request('email'),
'password' =>bcrypt(request('password'))
]);
session()->flash('message','Changes has been Applied'); //flash a succcess message
return redirect()->home(); // redirect to home after submitting the new user
}
}
My Route (not a resource route , just a native route )
// add new user routes
Route::get('add','AddController#create')->middleware('authenticated');
Route::post('add','AddController#store');
My Model
is the Built-In User.php model provided by laravel.
My View add.create.blade.php
<!-- this is the view of the add new user tab , extending master layout and it's components-->
#extends('layouts.master')
#section('content')
<div class="col-md-8">
<h3>Enter the Values of the new User</h3>
<form method="POST" action="add">
{{csrf_field()}}
<div class="form group">
<label for="name">*Name:</label>
<input type="name" class="form-control" id="name" name="name">
</div>
<div class="form group">
<label for="Email">*Email Address:</label>
<input type="email" class="form-control" id="email" name="email">
</div>
<div class="form group">
<label for="password">*Password:</label>
<input type="password" class="form-control" id="password" name="password">
</div>
<div class="form-group">
<label for="password confirmation">*Confirm Password:</label>
<input type="password" class="form-control" id="password_confirmation" name="password_confirmation" >
</div>
<br>
<div class="form-group">
<button type="submit" class="btn btn-primary">Add User</button>
</div>
#include('layouts.errors')
</form>
</div>
#endsection
that's what i have reached so far and i wish if any one tell me how to apply api to this code to make it function on mobile as well , i really appreciate any help in advance .
Right now you controller returns a view file - HTML template with some PHP variables. Your API doesn't need that HTML code, so first of all, you should get rid of it.
Your API route(in API case route is called 'endpoint') should return information in structured format - if you are using REST API, you should return data in JSON format(http://jsonapi.org/examples/ - example of JSON responses), if you are using SOAP - response should be in XML(for first time I would recommend you to use REST, as it's much simpler to build REST API).
A good practice would be to use Transformers while building your response(take a look https://medium.com/#haydar_ai/how-to-start-using-transformers-in-laravel-4ff0158b325f here for example).
You should also create your endpoints in api.php file - this file is specially for this needs. Don't forget that all routes in this file have a prefix of 'api'.
There is a great video-series in https://laracasts.com/series/incremental-api-development, in which simple REST api is build.
I am implementing a simple newsletter form using PHP and CodeIgniter as part of a big project.
My HTML code is as follows.
<form method="POST" action='http://sit.com/index.php/Users/subscribenews'>
<div class="input-group">
<input type="email" id="pkemailid" name="pkemailid">
<span class="input-group-btn">
<button class="btn btn-lg btn-primary" type="submit"> Go
</button>
</span>
</div><!-- /input-group -->
</form>
In my Controller, I am handling the value as
$emailid = $this->input->post('pkemailid');
When I do a var_dump of the $_POST variable, I get the following
array(0) { }
The biggest problem is that I am able to run this correctly on my WAMP Server on localhost but it does not work on the hosted server.
Interestingly, if I change the POST to GET, then it starts working.
this line
<input type="email" id="pkemailid" name="pkemailid">
try changing it to
<input type="text" id="pkemailid" name="pkemailid">
type="email" is html 5 only and i don't know for certain -- but codeigniter might not support html 5 form values.
===== edit
so my suggestion when you are at the hair pulling questioning reality stage of trying to find a bug - get a fresh new copy of codeigniter, install on your server, make sure you get the welcome page.
now make the simplest form possible and echo something out from the controller method to make sure that you are submitting the form to the correct method. Next add a hidden form field with a value, and echo out that value from your method.
If all that works, then its not your server you have bug in your original code. And if it doesn't work then you have an issue with the server.
I'm having a very frustrating (super-newbie) experience with Laravel 5.1.
Sure there must be something that I'm missing, but unfortunately I couldn't find anything on Laravel docs.
The problem is this (and I believe is even relatively simple): while all GET routes are working, the routes in POST are 'rerouting' me to the wrong place.
For instance, assuming that the controller is this:
namespace App\Http\Controllers;
use Illuminate\Routing\Controller as BaseController;
use View;
class PagesController extends BaseController {
public function hello(){
return view('hello');
}
public function register(){
//Registration rules
$inputData=array(
'name' => \Input::get('name'),
'email' =>\Input::get('email'),
'password' => bcrypt(\Input::get('password')),
);
createUser($inputData);
return view('stat');
}
private function createUser($inputData){
return User::create($inputData);
}
}
and given the route:
Route::get('/','PagesController#hello');
this one redirects me correctly to the view specified in the controller,at the method indicated.
A POST operation cannot be successfully performed, since
Route::post('/','PagesController#register');
with the form having:
<form action="/" method="post">
<input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">
<label for="name">User Name</label><br/>
<input type="text" name="name" id="name"/><br/>
<label for="name">E-mail</label><br/>
<input type="text" name="email" id="email"/><br/>
<label for="password">password</label><br/>
<input type="password" name="password" id="password"/><br/>
<input type="submit" value="auth!"/>
</form>
results in redirecting me to xampp home page.
For example, the "main registration page" is at this url:
http://localhost:8080/laravel/project1/public/
(GET OK)
and when I click on the submit button, I'm sent to
http://localhost:8080/
Just few more indicators for you to try and help me (I'm genuinely stuck):
1) I didn't use a VirtualHost (searched on the web, but had always no luck in configuring apache properly...good luck I've got xampp)
2) The page "hello" has a link that I used as a test:
Link
and it redirects me correctly to the sought-after
http://localhost:8080/laravel/project1/public/stat
3)In the POST method, I've used a dd($inputData) to see what was going wrong, and as a result I had...nothing. Not a blank page,just always the localhost page. This led me to think that somehow the controller method isn't called, since no dd(---) result got in page.
Hope someone can help.
Many thanks
Your domain is http://localhost:8080 , so when you set action to '/' , it goes to root. It`s not good practice , but your solution is to change :
<form action="/laravel/project1/public/" method="post">
I`d create a virtual host for the project in apache , so document root would be /laravel/project1/public/ .
you are posting your form to the root / that is why you are being routed to xampp page. To solve this problem, change your form action to this
<form action="/post/my/form" method="post">
in your routes
Route::post('/post/my/form','PagesController#register');