'rule_2' => [new CustomRule($request->input('rule_1'))]
Can I pass a value of another field to custom validation rule?
I need to validate rule_2 based on the value of rule_1 value, so I need to pass the value of rule_1 to a custom rule I create for rule_2, is it possible? Because I know that using a custom rule is simply the rule name without parentheses:
'rule_2' => [new CustomRule]
so how can I pass the value of rule_1 to this custom rule and conditionally set validation rules on it?
@Sinnbeck Thank you, didn't know it's allowed. Then this value will be available at the rule's constructor right?
Also, is it common? Or I should avoid this and find another solution?
@cooperino yeah exactly.. I use it like this myself
@Sinnbeck But then in the validation rules of the custom rule:
public function passes($attribute, $value)
{
is there any way to use the validation rules of Laravel? For example somehow for min max values have simple array:
['min: 3', 'max:10']
or I will have to use PHP:
if ($value > 3 && $value < 10) return true;
@cooperino Why not just add all validaiton rules?
'rule_2' => [new CustomRule($request->input('rule_1')), 'min: 3', 'max:10']
@Sinnbeck because rule_1 can have three options, and the min/max for rule_2 is different based on rule_1 value, that's why I feel that something is wrong with what I'm doing
@cooperino Then it is a complete separate rule, and and I would personally not depend on other rules. Just use php to check. While you can make a manual validator, and use that, I personally prefer pure php for a simple check like that.
I have my own custom validation rules for data and timestamps, and all of these are handled directly using carbon, not the date validator.
@Sinnbeck Oh, so you mean I should do completely different thing, and if I understand correctly it would be:
'multi_option' => ['required'],
'rule_2' => ['required_if: multi_option, value_1', 'min:3', 'max:10', 'regex: some_regex_1'],
'rule_3' => ['required_if: multi_option, value_2', 'min:2', 'max:8' ,'regex: some_regex_2'],
'rule_4' => ['required_if: multi_option, value_3', 'min:6', 'max:30', 'regex: some_regex_3'],
And I do not even need custom rule in this case
@cooperino I mean I would add a custom and have that check if it passes using simple php logic.
'rule_2' => [new CustomRule($request->input('rule_1'))]
@Sinnbeck But that is the situation right now. With the new approach I wrote above, it does the same (I think - perhaps just without the custom messages which aren't necessary), unless those required_ifs will not behave as expected
Because as above, it will only validate the rule (required_if) based on the value of the multi select field)
@cooperino required_if just ensures that the rule_2 is required, if multi_option is equal to value_1
@Sinnbeck But then it will have to continue with the other validation rules in that array and validate accordingly? so if rule_2 is required, and it contains more validation rules, then it will validate them as well?
And if user selected value_1 and the rule for value_1 is:
'rule_2' => 'rule_2' => ['required_if: multi_option, value_1', 'min:3', 'max:10', 'regex: some_regex_1'],
Then also check for the rest of the validation in that array (min, max, regex)?
@cooperino It will still validate them. It only either adds or remove the required validation rule.
You can use php to set up the array if you want
'rule_2' => array_merge(['required'], $request->multi_option === 'value1' ? ['min:3', 'max:10', 'regex: some_regex_1'] : []),
@Sinnbeck Oh so it will validate them if they are present, but if not - it will not validate, which is exactly what I need. What you mean is, that if they existed in the request I would need to worry that it will still be validated.
But in my case, they user selects only one of the options, so the rest will not exist at all, thus not be validated. So in my case it will work?
Did I understand correctly?
@cooperino It only changes the required rule. So remove the required parameter and see if it then passes if its empty (If I understand you correctly it should)
@Sinnbeck From some reason the following doesn't work at all (Not working, without any errors)
'multi_option_select' => ['required_unless:is_from_route_one,false', Rule::in(['value_1', 'value_2', 'value_3'])],
'rule_2' => ['required_if: multi_option_select, value_1', 'min:10','max:20'],
when I dd, these fields exist with a value
hi, here is my solution on Laravel8.
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Contracts\Validation\ValidatorAwareRule;
class MyCustomRule implements Rule, ValidatorAwareRule
{
/**
* validator instance
*
* @var \Illuminate\Validation\Validator
*/
protected $validator;
/**
* field name
*
* @var string
*/
protected $fieldName;
/**
* Create a new rule instance.
*
* @return void
*/
public function __construct($fieldName)
{
// you can pass it when instanciating the class such as new MyCustomRule('rule_1')
$this->fieldName = $fieldName;
}
/**
* set validator instance
*
* @param \Illuminate\Validation\Validator $validator
* @return $this
*/
public function setValidator($validator)
{
$this->validator = $validator;
return $this;
}
/**
* determine if validation passes
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
$fieldValue = $this->validator->getValue($this->fieldName);
// continue your logic here
}
/**
* Get the validation error message.
*
* @return string
*/
public function message()
{
// your custom error message here
}
}
On Laravel9 or Newer.
<?php
namespace App\Rules;
use Closure;
use Illuminate\Contracts\Validation\DataAwareRule;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Validation\Validator;
class TotalHundred implements DataAwareRule, ValidationRule
{
/**
* All of the data under validation.
*
* @var array<string, mixed>
*/
protected $data = [];
/**
* The validator instance.
*
* @var \Illuminate\Validation\Validator
*/
protected $validator;
/**
* The field name passed to the rule.
*
* @var string
*/
protected $fieldName;
/**
* Create a new rule instance.
*
* @return void
*/
public function __construct($fieldName)
{
// you can pass it when instanciating the class such as new MyCustomRule('rule_1')
$this->fieldName = $fieldName;
}
/**
* Set the data under validation.
*
* @param array<string, mixed> $data
*/
public function setData(array $data): static
{
$this->data = $data;
return $this;
}
/**
* Set the current validator.
*/
public function setValidator(Validator $validator): static
{
$this->validator = $validator;
return $this;
}
/**
* Run the validation rule.
*
* @param \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString $fail
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$fieldValue = $this->data[$this->fieldName];
// continue your logic here
}
}
@katayamahide, this is one of the most adequate options. Thank you.
Please or to participate in this conversation.