Closed iannazzi closed 8 years ago
Hi @iannazzi Can you show me your Restangular code?
Meanwhile I think you can use this code:
$data = $request->only(['name', 'company', ..etc])
You should get an array with the keys you provided even if there's no data submitted
This is what I have found: SAFARI will not post empty elements, Chrome works as I might expect, posting all elements. I actually believe SAFARI is the correct implementation as it will reduce the amount of data transmitted.
When I enter "1" for company and leave everything else blank in Safari and Chrome, I get the following request data out of the console:
SAFARI:
{"company":"1"}
Chrome
{company: "1", name: "", email: "", phone: "", password: "", password_confirmation: ""}
To confirm your suggestion: `$request->only(['name', 'company', 'phone', 'email', 'address', 'password', 'password_confirmation' ]);' will nullify missing data....Thank you for that!
HOWEVER I assume I still want to use laravel's Validator, unless you have other recommendations
$validator = $this->registrationValidator($request->all());
Which leads me to the error described originally,$data['empty input field']
may fail.
So it sounds like we need to normalize incoming browser data.
This seems a bit repetitive and verbose:
$validator = $this->registrationValidator($request->only(['name', 'company', 'phone', 'email', 'address', 'password', 'password_confirmation' ]));
$data = $request->only([
'name',
'company',
'phone',
'email',
'address',
'password',
'password_confirmation' ]);
$system = System::create($data);
My thoughts are to write my own data validator or to extend the validator and nullify missing optional data, but I would think you have a better suggestion.
Here is my restangular code:
submit(){
var data = {
company: this.company,
name: this.name,
email: this.email,
phone: this.phone,
password: this.password,
password_confirmation: this.password_confirmation
};
this.API.all('register').post(data).then((response) => {
this.ToastService.show(response);
//console.log(data);
//console.log(response);
});
}
Hi @iannazzi Can you please use three backticks and then an empty line "```" to fix the formatting of your code Thanks!
I may have a solution, but it is early, I have 100 more controllers to make....
In the controller I use the validator method you guys made on the base controller, however I added another method to go through the validation rules and request->only those rules.
<?php
namespace App\Http\Controllers;
use ...
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
use Helpers;
/*Fixes dingo/api form request validation https://github.com/dingo/api/wiki/Errors-And-Error-Responses#form-requests*/
public function validate(Request $request, array $rules, array $messages = [], array $customAttributes = [])
{
$validator = $this->getValidationFactory()->make($request->all(), $rules, $messages, $customAttributes);
if ($validator->fails()) {
throw new ValidationHttpException($validator->errors());
}
return $this->normalizeBrowserPostData($request, $rules);
}
/**
* normalize post data coming in, some browsers post empty strings, some do not.
* @param $request
* @param $rules
* @return array
*/
public function normalizeBrowserPostData(Request $request, array $rules)
{
foreach($rules as $key => $rule)
{
$input[] = $key;
if (strpos($rule,'confirmed') !== false)
{
$input[] = $key . '_confirmation';
}
}
return $request->only($input);
}
}
in the controller there is one call:
public function postRegister(Request $request)
{
$data = $this->validate($request, $this->validationRules());
//data is now all set.....
$system = System::create($data);
What do you think?
@iannazzi I am not sure you need the normalizeBrowserPostData function..
Have you tried defining your variables in the constructor?
constructor(){
this.name = '';
this.company: '';
//etc..
}
Confirmed, added the 'init' code in the constructor and it works as expected by posting all inputs.
I guess I would consider this repeating myself. For every form I define what to post, but then also have to init every post form.
I also feel like this needs to be handled server-side as JS can be manipulated. Correct me if I am mistaken, but I treat all incoming data guilty until proven innocent.
Finally I believe safari has the correct approach, minimize transmitted data.
That said, on the server I was looking at the laravel validator and dingo/api for a solution.
I really only want to define the validation once, if the input data was not required and there is no post data for that input, then go ahead and create the data as null. normalizeBrowserPostData will create those missing post fields.
I was wondering if the transformers of dingo/api normalized browser data. I did not see that they did.
I was also wondering if my input/post data names should be made to not match my database names, which I believe the dingo/api transformer is meant to be used to convert the data keys.
My final thoughts on cleaning up post data is that there should be a post data transformer and for missing post data the transformer should init the missing browser data. Based on all these points would you consider that the correct approach for cleaning up the incoming data?
I never worked with Transformers, but as far as I know they're only for the response.. however you might be able to use them the other way around.. I'm not really sure
I never had this issue mainly because I had ->nullable()
at the database level when appropriate
and I personally like to initialize my variables to make it obvious what I'm expecting..
sometimes I put them inside an object, something like:
this.data = {
first_name: '',
last_name: ''
};
However if you think that your solution can be fixed with a function similar to normalizeBrowserPostData
then yeah why not - it really depends on what you're doing
it's not a bad idea to have your db column names and json fields matching
Great, I think we summed up the problem and several solutions in case others experience the issue.
Do you have a suggestion/example for converting angular post data to eloquent model saving?
For example It looks like angular will not post an element where no data was entered. Therefore an input box called
'name'
will not be in the post data if you leave it empty.Then you get the error when trying to do this:
model->name = $post_data['name']; //there is no name posted
I am still using laravel's validator, below is the code to demonstrate.