I want to validate a "price" field in Laravel.
The price should only contain numbers without (.) or (,) and cant start with 0 as well.
Eg
2500 // Pass
02500 // Fails
12.12 // Fails
12,12 / Fails
The rule I have now looks like this:
'price' => 'required|integer|not_in:0',
It seems to work with the example above, however I dont understand it. Why does not integer allow something like 0123 with a starting zero. I just want to make sure that my rule works as excpected and that I dont miss something
Thanks
This works for me:
'price' => 'required|numeric|gt:0',
You can format the input before sending it to the validator in your Request class.
public function formatInput()
{
$input = array_map('trim', $this->all());
$input['price'] = (int)($input['price']);
$this->replace($input);
return $this->all();
}
Then you can use
'price' => 'required|integer|min:0',
Hope this helps
if you're not sure about the rule "integer", you can use the regex expression validation as following :
'price' => 'required|regex:^[1-9][0-9]+|not_in:0',
I had some issue same way as you, and since then i always used the regex validation for this kind of requirements. Furthermore it allow you to take back the same regex if you want to make a front validation with js.
Here is the laravel function allowing to validate integers :
public function validateInteger($attribute, $value)
{
return filter_var($value, FILTER_VALIDATE_INT) !== false;
}
SO it's PHP itself that is concerned by this behavior. PHP tells us this thing about FILTER_VALIDATE_INT :
Validates value as integer, optionally from the specified range, and
converts to int on success.
No other informations are set by PHP about the "0" value, but it's known that this function doesn't consider numbers starting by "0".
Use regex rule to not allow for integer with starting 0
'price' => 'required|integer|not_in:0|regex:^[1-9][0-9]+',
Related
I made a unique validation in 1 field, so for example I input "pizza", while the "pizza" already exists, so it automatically doesn't work but if I input "Pizza" the letter "p" is large it still passes, how do I fix it?
so I want when validating he doesn't pay attention lowercase or uppercase.
This my code now :
$exists = Category::where(\Str::lower('name'), '=', \Str::lower(request('name')))->orderBy('name')->first();
if ($exists) {
return redirect()->route('categories.index')->with('error', 'Nama kategori sudah ada');
} else {
Category::create(request()->all());
}
\Str::lower() actually does nothing for you here since it just returns string 'name', which is then passed as first argument in Builder::where() function.
What you can do it take advantage of Builder::whereRaw() function and do something like following
Category::whereRaw('LOWER(`name`) = ?', \Str::lower(request('name')))->first()
But Eloquent build also works if you do something like (do not use = sign)
Category::whereName(request('name'))->first()
or
Category::where('name', request('name'))->first()
In laravel 7, the $request->all() or the $validator->valid(), always return an array of values, key assign is correct, but the values are always strings.
I need the validator to transform the field to the rules i made.
Example in rules for validation : ['no' => 'required|integer|min:1',...]
Example of the output of validation->valid() : [ "no" => "1231" ] - string typed, i need this to be integer like : [ "no" => 1231 ]
I dont want to cast every field one by one... what i'm doing wrong ?
NOTE
All the validations works well, it's only the output of the fields that i want to match the validation, if i say the field is integer, the result of the validation must be integer and not string.
I just resolve this problem :
Create a FormRequest file, and put the validations, rules and messages there.
I dont know why... in the last version : my validations , rules and messages stay in the controller file.
Clear cache, everything ok.
QUESTION UPDATED: I found out more information and therefor changed my question.
I want to save my user with his license number, but only if he selects that he has a license. I have three possible values for the pilot_type field (ROC, ROC-light and recreative) and only the last option should allow for an empty string to be submitted.
In order to achieve this, I wrote the following validation function:
$validator
->add('license_nr', 'present_if_license', [
'rule' => function ($value, $context) {
return $context['data']['pilot_type'] == 'recreative' || !empty($value);
},
'message' => "If you don't fly recreatively, a license number needs to be supplied"
]);
The problem is that setting any validation rule on a field will trigger an additional check in the CakePHP Model class that will reject the value if it's empty. I tried to fix this by adding ->allowEmpty('license_nr'), but that rule makes for the model to accept an empty string without even running my custom function. Even putting them in order and using 'last' => true on my custom rule doesn't resolve this problem:
$validator
->add('license_nr', 'present_if_license', [
'rule' => function ($value, $context) {
return false;
// return $context['data']['pilot_type'] == 'recreative' || !empty($value);
},
'last' => true,
'message' => "If you don't fly recreatively, a license number needs to be supplied"
])
->allowEmpty('license_nr');
How do I make CakePHP run my custom function in order to see if the field can be empty, rather than just assuming that it can never be empty or must always be empty?
By default fields aren't allowed to be empty, so that's the expected behavior and you'll have to explicitly allow empty values.
In order to achieve what you're trying to do, instead of using an additional rule, you should customize the allowEmpty() rule, use the second argument to supply a callback (note that unlike rule callbacks it will receive a single argument that provides the context).
So you'd do something like this, which you may need to modify a bit, for example depending on whether you need it to work differently for creating ($context['newRecord'] = true) and updating ($context['newRecord'] = false) records:
->allowEmpty(
'license_nr',
function ($context) {
return $context['data']['pilot_type'] === 'recreative';
},
"If you don't fly recreatively, a license number needs to be supplied"
)
As of CakePHP 3.7 you can use allowEmptyString(), it will work the same way, you just need to swap the second and third arguments, as allowEmptyString() takes the message as the second argument, and the callback as the third argument.
See also
Cookbook > Validation > Conditional Validation
during validation I would like to compare with an attribute from another model. Is it possible? If yes, I would be grateful if you would point me to the right direction. I imagine it somehow to access model B in model A, but maybe my logic is not good, and I have no clue how can this be achieved. Thanks.
You can try to build an inline validator see this doc for validator and for inline validator
this is a brief sample
public function rules()
{
return [
.....
['my_field', 'validateMyCompare'],
....
];
}
public function validateMyCompare($attribute, $params)
{
if (YourModel::findOne(['your_model_field'=> $attribute]) {
$this->addError($attribute, \Yii::t('view', 'The fields don't match.'));
}
}
I've solved it this way:
public function getRelatedmodel() {
return $this->hasOne(\app\models\Relatedmodel::className(), ['id' => 'relatedId']);
}
public function getMotherRelatedAttribute() {
if ($mother = Model::findOne($this->mother)) {
return $mother->relatedmodel->attribute;
}
}
And in rules:
['attribute', 'compare', 'compareAttribute' => 'MotherRelatedAttribute', 'operator' => '<=', 'on' => self::SCENARIO_CREATE_RST],
compare
[
// validates if the value of "password" attribute equals to that of "password_repeat"
['password', 'compare'],
// validates if age is greater than or equal to 30
['age', 'compare', 'compareValue' => 30, 'operator' => '>='],
]
This validator compares the specified input value with another one and make sure if their relationship is as specified by the operator property.
compareAttribute: the name of the attribute whose value should be compared with. When the validator is being used to validate an attribute, the default value of this property would be the name of the attribute suffixed with _repeat. For example, if the attribute being validated is password, then this property will default to password_repeat.
compareValue: a constant value that the input value should be compared with. When both of this property and compareAttribute are specified, this property will take precedence.
operator: the comparison operator. Defaults to ==, meaning checking if the input value is equal to that of compareAttribute or compareValue. The following operators are supported:
==: check if two values are equal. The comparison is done is non-strict mode.
===: check if two values are equal. The comparison is done is strict mode.
!=: check if two values are NOT equal. The comparison is done is non-strict mode.
!==: check if two values are NOT equal. The comparison is done is strict mode.
: check if value being validated is greater than the value being compared with.
=: check if value being validated is greater than or equal to the value being compared with.
<: check if value being validated is less than the value being compared with.
<=: check if value being validated is less than or equal to the value being compared with.
I have a custom validation rule to make sure that a non-zero price is set in a field. I have a placeholder (0.00) in the field to keep users from entering things like dollar signs. When I go to validate for a non-zero entry, however, $this->data[$this->alias]['price'] is '0.00' in my test, but the validation is working - it invalidates. But when I put in 1000.00, it's also invalidating.
One thing I can't find is what/how to return from a custom validation field to invalidate the field. Currently, the code is:
public function notZeroPrice($check){
if ($check == '0.00')
return true;
return false;
}
The docs aren't clear on the structure of $check either.
If it validates, return true. If the doesn't, return false.
However, your validation method is flawed to begin with. $check is an array if you debug it, so your method is always going to return false. Secondly, you want to test if its > 0, not just equal to '0.00'. You'll be comparing 2 string so that won't work, either.
Instead, return true if the value is greater than 0 (int). You can get it value out of the array easily by using array_shift($check);
return array_shift($check) > 0; // or something similar.
You may even get away with 'rule' => array('comparison', '>', 0), core validation.
(I'm assuming not zero for a price also means not a negative price)