I have a form in Laravel and the submission and validation works, but I'm doing custom validation to check the data against the database (for sanitization) as well.
The issue is, I only want to do this validation IF each of the fields is filled out. In other words, if an input isn't required thus not filled out, I don't want it to fail because of it not matching data in the database.
For instance, I have a form input on my blade:
<td>{!! Form::select('productNumber', $img->productNumber) !!}</td>
and in the controller I'm checking this against the service to make sure it's valid data
if(!$productCheckService->validGroupCode($request->productNumber))
return back()->withErrors("Invalid group: ".$request->productNumber);
This works if filled out, but if the field is empty I want to bypass that check. In other words, the field isn't required so the data validity check shouldn't be required on a possibly null/empty field
I'm doing this below but it still is failing if it's empty for some reason. Am I totally missing something? I would think that checking that it's not empty before the check should suffice.
if(!empty($request->productNumber))
if(!$productCheckService->validGroupCode($request->productNumber))
return back()->withErrors("Invalid group: ".$request->productNumber);
You can use Laravel 'sometimes' attributes, so if your field is not present in request array it will bypass from validation.
$v = Validator::make($data, [
'productNumber' => 'sometimes|required|number',
]);
Related
I have a template that allows adding new lines. Example: I want to add multiple products at once to a store, so I can add them all at once, through those lines that replicate themselves. The problem is that I need to validate these fields, they are all mandatory. I'm implementing so that I can walk through each one and leave it compulsory. However, I came across another problem, Laravel is telling me that my field is empty, but it is not. I would like to know how I can solve it, thank you in advance.
Here is my code to FormRequest
public function rules()
{
$rules = [];
foreach($_POST['esp'] as $key => $esp){
$name_field = "esp[" . $key . "]" . "[esprqe]"; //name of my field is complicated even as it is time based
$rules[$name_field] = 'required';
}
return $rules;
}
My template is big, no need to show.
message I receive: esp[1553533952015][esprqe]: ["The esp[1553533952015][esprqe] field is required."]
My input is not empty, I do not know what the problem is
You state the name of your field 'esprqe' is time based and complicated. This is likely the cause of your problem.
The esp['.$key.'] field is probably fine, as this field is transferred from your form. However, the value that goes into esprqe, if that is being generated in your server side code above (I don't know, you haven't provided how this field is generated), and if the rules are looking for that field to match a time-based generated field on the form... those values won't match and you will have a non-value coming into your method above.
This would very likely generate a message
["The esp[1553533952015][esprqe] field is required."]
If this is your issue, you can test by first creating a simple numbered index for the esprqe field that will be matched on both form and method. If this succeeds, you can then increase the complexity using a common generator so that the rules section knows exactly what the name of the field is. Time can't be common between form creation and rules creation - thus perhaps the reason for the failure.
You need use "dot notation" to validate attributes within an array.
$name_field = "esp.$key.esprqe";
Laravel Docs: validating arrays
In my registration form, I have a checkbox where a user can accept to receive newsletters.
In create function I want to display all passed data:
protected function create(array $data)
{
dd($data);
}
The name of my checkbox field is newsletter. When I do dd(), I don't get the value for the newsletter, only for: name, email and password.
If I add this newsletter to Validator then it is shown.
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6|confirmed',
'newsletter' => 'required',
]);
}
Now, when I do dd() it is passed, but I don't want this checkbox to be required. It should be optional. Should I change something in Validator or?
Regardless of the backend, when a checkbox is not checked, its value won't be sent as part of the request to the server. That's how browsers work and that's why you won't be seeing a newsletter field when dumping the request.
However, when you use Laravel's validator and mention the field in the rules, Laravel does it for you and sets its value. To not to make it required, use the sometimes rule.
That would do it just for the purpose of dumping the data. But when implementing the real logic, instead of dumping data, you'll hopefully be utilizing the given request instance, facade or helper which will return a falsy value for non-existent parameters. So, you're just fine without adding the additional rule.
Or, you can set a default value for the newsletter field making sure if the data is not there, new registrations will happen with the desired default state.
By the way, you wanna make sure that your controller method is accepting a Request instance instead of an array.
Your newsletter field is a checkbox. When a html form is submitted and the checkbox is not checked, this field will not be available in the posted data. If the checkbox is checked it will be available. This is default html behavior, nothing you can do about this.
To check if the checkbox has been checked in your code, you can use the following:
$checked = array_key_exists('newsletter', $data);
I am wondering how to pass to inputs old value if user fails the laravel validation. I've tried to use:
Example: {{ Request::old('mail') }}
And: {{ old('mail') }}
I think that if user fails laravel validation input values are deleted.
Anyone has some idea to solve the problem?
With laravel 5.2 If you’re redirecting back to the form, a really useful method is withInput():
return redirect()->back()->withInput();
This method has no parameters and what it does is saves the old form values into Session. Then in the form you can use function old($key) to retrieve those values for every field – that would be a separate topic about the Forms.
You need to do something like this, if invalid
return Redirect::to('your_ulr')->withInput(Request::all());
I'm using ZF2 and mysql, but the question is platform-independent. I have a data transfer object Organization that gets hydrated from an html form. OrganizationMapper has a save method that (1) gets Organization as an argument and (2) fills a couple of database tables one after another.
Suppose the 1st table gets filled ok, but the 2nd doesn't because one of the properties of Organization isn't set (not null constraint on a column). The user gets an error, but the 1st table is already filled. If he attempts to submit the form again, but this time with all html fields filled, all the tables get filled ok, but the 1st has a previous unused row.
How could I avoid this situation?
I thought of checking for empty values with if's in the mapper's save method, but it doesn't seem elegant. I know about the InputFilter validations in ZF2, but these check the user input in the form, they don't check things when the php code communicates with the database.
Any help?
The best way is to validate all the data before you start writing it to the database.
I didn't use ZF2 and this solution is actually framework-dependent, so you need to check the ZF2 docs. For example, in Yii, you just define validation rules for every field of the model, so you can ensure that your Organization contains all the data before you start saving it to the database, probably something similar is possible in Zend.
Note, that validation doesn't mean just to check for empty values, you may need to verify different things, like: "email is correct email like xxx#yyy.com", "name is not empty", "name length is more than 3 chars", "name length is less than 1000 chars" and so on.
For Yii it roughly looks like this:
class Organization extends ActiveRecord {
...
// here we define the validation rules
public function rules() {
return [
// name is required
['name', 'required'],
// check min / max length
['name', 'string', 'min' => 3, 'max' => 12],
// check if email is valid
['email', 'email']
];
}
}
Now you can do $organization->validate() to make sure everything is correct (also when you do $organization->save() the rules will be checked before saving to the database).
And one more solution to protect from the inconsistent data is to use transactions. In the case you write to multiple tables, you anyway need them, even if you validated everything. Unexpected things happen, so it is better to protect your saving code like this (pseudo-code):
$transaction->start();
try {
$table1->writeSomeData();
$table2->writeMoreData();
$transaction->commit();
} (catch Exception $e) {
$transaction->rollback();
}
Again, check your framework documentation, it probably supports this in some way.
I was investigating CakePHP (2.3.4) Model::save method to insert new records and ran into a little snag:
//Two fields provided, email field intended to fail validation
$data = array('Member' => array(
'username' => 'hello',
'email' => 'world'
));
$this->Member->create();
var_dump($this->Member->save($data, true));
The above save() will return false and no data will be written to the database. However if I change the data to:
//One field provided, intended to pass validation
$data = array('Member' => array(
'username' => 'hello'
));
then save() will attempt to write a new record to database with a blank email field. I realize that skipping validation for unspecified fields might be a useful behavior during updates, but is there a CakePHP recommended way to handle partially empty data sets when creating new records? Thanks a lot.
Edit:
Thanks to Sam Delaney for the tip. In case anybody else gets stumped, this did the trick: CakePHP Data Validation: field 'required' key
This key accepts either a boolean, or create or update. Setting this key to true will make the field always required. While setting it to create or update will make the field required only for update or create operations. If ‘required’ is evaluated to true, the field must be present in the data array. For example, if the validation rule has been defined as follows:
I had originally baked the model and forgotten that required => true was left out of the validation rule. Setting it to true or 'create' would've avoided me blank records getting inserted due to gibberish data array.
IMHO what you've experienced is the desired behavior. Consider that you have the same two fields within a form and the user provides a value for only username. Both username and email field are submitted even though email is empty. Then on the server, you try to save the record only to find out that it has failed validation which you feedback to the user. On the other hand, perhaps in your system it is perfectly possible to create a user without requiring an email (for example root access account), CakePHP's validation implementation allows both of these scenarios.
If this flexibility isn't what you desire, just set the required attribute for your validation rule as true:
public $validate = array(
'email' => array(
'rule' => 'email',
'required' => true
)
);
This will satisfy your all or nothing requirement.