Laravel validation: exclude size check when field not required - laravel

I have validation in Laravel application, but I can't seem to make it work.
I am making validation on Supplier model not request.
public function requestOpening(Supplier $supplier)
{
$validator = Validator::make($supplier->toArray(), $this->fullValidationRules());
if ($validator->fails()) {
return redirect("open-new/supplier/{$supplier->id}")
->withErrors($validator);
}
// ...
}
I want hfm_code to be required only when is_hfm == 1. I tried both:
'hfm_code' => 'size:6|exclude_if:is_hfm,0',
and
'hfm_code' => 'size:6|required_if:is_hfm,1',
In both scenarios I get validation error:
The hfm code must be 6 characters.
How do I ignore size check when is_hfm == 0 ?

The order seems to matter here:
'hfm_code' => 'exclude_if:is_hfm,0|size:6'
should work. I think this is because it evaluates rules in order and will ignore the remaining ones if exclude_if passes

Related

How can I validate GET controller params in CakePHP 2?

Given this on the model:
public $validate = [
'amount' => array(
'rule' => array('comparison', '>=', 0),
'message' => 'You must buy over 0 of this item!'
)
];
How can I validate param #2 of the below?
public function buy(int $item, int $amount) {
Validation seems to be built only for POST, which I'd like to opt out of here.
First things first, modifying the database with GET requests is an anti-pattern for many different reasons. Even if you assume a friendly user agent (which you never should!), browsers can behave quirky and do unexpected stuff like for example sending GET request multiple times (that is perfectly valid as GET is not ment to modify data), which they usually won't for POST/PUT/DELETE.
I would strongly suggest to change your endpoint to handle POST requests instead.
That being said, you can generally validate whatever you want, the validation mechanisms first and foremost just validate data, they don't know or care where it stems from. You can hand over whatever data you want to your model, and let it validate it:
$data = array(
'item' => $item,
'amount' => $amount,
);
$this->ModelName->set($data);
if ($this->ModelName->validates()) {
// data is valid
} else {
// data is invalid
$errors = $this->ModelName->validationErrors;
}
Moreover you can use CakePHP's validation methods completely manually too:
App::uses('Utility', 'Validation');
$isValid = Validation::comparison($amount, '>' 0);
This example of course doesn't make too much sense, given that $isValid = $amount > 0 would do the same, however it should just show that you can validate anything everywhere without models being involved.
See also
Cookbook > Models > Data Validation > Validating Data from the Controller
Cookbook > Models > Data Validation > Core Validation Rules

Validation check field not empty

We're trying to have one or another field validated, the second field only shows up when they choose to not fill in the first. So we only need the second field to validate if the first is left empty from them skipping over it.
For context its to checek the make of an appliance, we have a list of brands/makes known to the system but an option to write it manually if yours doesnt show up. But we need to validate that the manual entry field isn't empty, but only if they've skipped over the first list.
'single_item_make' => 'required_if:policy_type,single|required_if:single_item_make_other,',
'single_item_make_other' => 'required_if:policy_type,single|required_if:single_item_make,'
We tried the above and it didnt work, we cant seem to find anything in the docs about checking fields for being empty.
Only one of these two fields will be submitted at a time.
You can not combine the required_if with the required_without in this case, because it conflicts.
In your current code, the first rule on both is:
required_if:policy_type,single
Which requires both fields if policy_type === 'single', if 1 of the fields is empty this validation will fail.
A solution might be to use complex conditional validation, like so:
$v = Validator::make($data, [
'policy_type' => [
'required',
'in:single,x,y', // ?
],
// some other static validation rules you have
]);
// conditional validation based on policy_type === 'single';
$v->sometimes('single_item_make', 'required_without:single_item_make_other', function ($input) {
return $input->policy_type === 'single';
});
$v->sometimes('single_item_make_other', 'required_without:single_item_make', function ($input) {
return $input->policy_type === 'single';
});
This will only check that both can't be empty at the same time and that one field is required when the other one is empty.
However, this will leave the option for the user to fill in both.
If you would want to validate that both can't be empty, but only 1 can be set at the same time (xor), you would have to extend your validator as this does not exist in Laravel.
Put this in your AppServiceProvider's boot() method:
Validator::extendImplicit('xor', function ($attribute, $value, $parameters, $validator) {
return empty($value) || empty(data_get($validator->getData(), $parameters[0]));
});
Then you can use:
$v->sometimes('single_item_make', 'required_without:single_item_make_other|xor:single_item_make_other', function ($input) {
return $input->policy_type === 'single';
});
$v->sometimes('single_item_make_other', 'required_without:single_item_make|xor:single_item_make', function ($input) {
return $input->policy_type === 'single';
});
In this case, required_without makes sure that if 1 is empty the other 1 is required and the xor validation makes sure that if 1 is set, the other 1 can not have a value.
You can add custom error messages in your validation or use a custom validator and pass those validation messages there.
More info: https://laravel.com/docs/5.7/validation#conditionally-adding-rules
I have not tested both pieces of code, but they should work.
As the required_without docs suggest, you need to use it as below:
'single_item_make' => 'required_if:policy_type,single|required_without:single_item_make_other,',
'single_item_make_other' => 'required_if:policy_type,single|required_without:single_item_make,'

Laravel validation 'different' fails when other attribute is null

Hello I'm having troubles with the different validation.
I have 2 variables that can be null. What I want to achieve is whenever the variable is present, force it to have exactly 5 digits and not to have the same value.
These are the rules that I've set:
'zip_departure' => 'nullable|digits:5',
'zip_arrival' => 'nullable|different:zip_departure|digits:5',
The problem is when I set zip_departure as null it throws up a validation error saying both parameters cannot have the same value. But if I dd() both variables they have:
'zip_departure': null
'zip_arrival': '28100'
What am I missing here?
I'm using Laravel 5.6
As of Laravel 5.6 the validator explicitly checks whether the other value is not null.
public function validateDifferent($attribute, $value, $parameters)
{
$this->requireParameterCount(1, $parameters, 'different');
foreach ($parameters as $parameter) {
$other = Arr::get($this->data, $parameter);
if (is_null($other) || $value === $other) {
return false;
}
}
}
framework/src/Illuminate/Validation/Concerns/ValidatesAttributes.php:432
That's why different:var2 works but different:var1 doesn't.
As of Lravel 5.8 and higher this is fixed
Try this code
'zip_departure' => 'bail|nullable|digits:5',
'zip_arrival' => 'bail|nullable|required_with:zip_departure|different:zip_departure|digits:5',
bail is for : Stop running validation rules after the first validation failure
Laravel Validation Rule
required_with is for: The field under validation must be present and not empty only if any of the other specified fields are present.
Laravel Validation Rule
Hope this helps...

Customized validation rule on laravel form request validation

I do have a registration form in my laravel 5.4 application and laravel form request validation is used for server side validation. Some fields in this form are populated dynamically using calculations in javascript which need to be validated against user inputs.
The user input fields in the form are 'quantity', 'rate' and 'discount'.
The populated fields are 'total' and 'bill_amount'.
What i need to validate are :
Check 'total' equal to 'quantity' * 'rate'.
Check 'bill_amount' equal to 'total' - 'rate'
I would prefer laravel form request validation methods for this validation. I have tried to use methods like After Hooks and conditionally adding rule etc. and failed.
In simple words the requirement is : check if a field is equal to product of other two fields, and invalidate if not equal and validate if equal.(using form request validation.)
Thanks in advance!
After a long time I was able to find this solution.
Form request After Hooks can be used to achieve the result:
[I was unable to find this logic before]
public function withValidator($validator)
{
$quanty = $this->request->get("quantity");
$rate = $this->request->get("rate");
$billAmount = $this->request->get("bill_amount");
$validator->after(function ($validator) {
if(($quanty * $rate) != $billAmount) {
$validator->errors()->add('bill_amount', 'Something went wrong with this field!');
}
});
}

Model rule variable required without scenario (Yii2)

How can I create a model rule that's only required when a certain value from the Database is 1?
I tried using a 'required', 'when' rule but that doesn't seem to update the client-side JavaScript.
I also tried a custom inline validator but that doesn't seem to post an empty field.
Scenario's aren't an option I think as I have 6 fields and can have any combination of required/not required.
EDIT
At the moment I just never add the required rules, instead of directly returning the rules I store them in a variable. $rules = []
Then before I return the variable I add the required options to the array.
if($x->x_required)
$rules[] = ['your-field', 'required', 'on' => 'your-scenario'];
This is a quickfix and I don't really like it, but it works. I'm not sure if there is a better way of doing this.
You need to use combination required with when, but for client side validation you need additionally specify whenClient property.
Example (add this to your rules()):
[
'attributeName',
'required',
'when' => function ($model) {
return $model->country == Country::USA;
},
'whenClient' => function (attribute, value) {
return $('#country').value == 'USA';
},
],
Official docs:
RequiredValidator
Validator $when
Validator $whenClient

Resources