-
-
Notifications
You must be signed in to change notification settings - Fork 255
requiredWith and "value" #327
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This is particularly useful for validating Conditional Fields. ProblemImagine you have a very simple payment information form, here's the initial premise.
Now here's some very simple markup to visualize it: <form method="post">
<select name="payment_method" required>
<option value="">Payment Method</option>
<option value="credit_card" selected>Credit Card</option>
<option value="bank_account">Bank Account</option>
</select>
<input name="credit_card_number" placeholder="Credit Card Number" value="1" required>
<input name="bank_account_alias" placeholder="Bank Account Alias" value="" required>
<input type="submit" value="submit">
</form> Now ideally, you wouldn't show the Bank Account Alias field when you selected Credit Card as your payment method and viceversa. You'd probably use some JavaScript, either vanilla or most probably a frontend framework to show/hide fields according to the Payment Method selection. Here's a very simple example using AlpineJS just to prove a point. AlpineJS implementation<script src="//unpkg.com/alpinejs" defer></script>
<form method="post" x-data="{payment_method: ''}">
<select name="payment_method" required x-model="payment_method">
<option value="">Payment Method</option>
<option value="credit_card" selected>Credit Card</option>
<option value
8000
="bank_account">Bank Account</option>
</select>
<input name="credit_card_number" placeholder="Credit Card Number" value="1" required x-show="payment_method == 'credit_card'">
<input name="bank_account_alias" placeholder="Bank Account Alias" value="" required x-show="payment_method == 'bank_account'">
<input type="submit" value="submit">
</form> The problem then becomes validating the initial premise with Valitron. See Credit Card Number and Bank Account Alias can't be required at the same time, so you'd need another either built in or custom validation rule to handle their validation. Solution A - Within Valitron ❌Baked in
The ideal solution for me would be something baked into Valitron, a View full example in PHPSandbox. $rules = [
'required' => [
'payment_method',
],
'requiredWhen' => [
[
'credit_card_number',
[ 'payment_method' => 'credit_card' ]
],
[
'bank_account_alias',
[ 'payment_method' => 'bank_account' ]
]
],
'creditCard' => ['credit_card_number'],
'regex' => [
[ 'bank_account_alias','/[a-zA-Z0-9]{1,30}/']
]
]; Custom Validation Rule
However, since its not currently baked in, the next best thing would be a Custom Validation Rule, lets explore this. View full example in PHPSandbox. This is the custom validation rule I came up with, it obeys the same format as the previous solution. Valitron\Validator::addRule('requiredWhen', function($field, $value, array $params, array $fields) {
$conditions = $params[0];
foreach( $conditions as $condition_field => $condition_value ) {
if( $fields[$condition_field] == $condition_value
&& empty($value) ) {
return false;
}
}
return true;
}, 'is required.'); The problem is, imagine recieving incorrect $_POST = array(
payment_method => 'credit_card',
credit_card_number => '',
bank_account_alias => 'wrong field is filled out, should be credit_card_number'
); Since Now we could solve this with the second parameter of the Another way to solve this would be for Solution B - Outside Valitron ✔View full example in PHPSandbox. Sadly, this was a requirement in one of my projects, so I was forced to solve it outside of Valitron. My solution involves a simple function which takes in the validator (for now, its just to call the This is heavily inspired in the function when( $validator, $conditions, $then_rules, $else_rules = [] ) {
$condition_validator = new Valitron\Validator( $validator->data() );
$condition_validator->rules( $conditions );
$conditions_passed = $condition_validator->validate();
if( $conditions_passed ) {
return $then_rules;
}
return $else_rules;
} The usage is pretty straightforward, we will merge regular rules with rules created by the $v = new Valitron\Validator( $_POST );
$rules = array_merge_recursive(
[
'required' => ['payment_method']
],
when(
$v,
[
'required' => [ 'payment_method' ],
'regex' => [
[ 'payment_method', '/^credit_card$/' ]
],
],
[
'required' => ['credit_card_number'],
'creditCard' => ['credit_card_number']
]
),
when(
$v,
[
'required' => [ 'payment_method' ],
'regex' => [
[ 'payment_method', '/^bank_account$/' ]
]
],
[
'required' => ['bank_account_alias'],
'regex' => [
[ 'bank_account_alias','/[A-z\.]{6,30}/']
]
]
)
);
$v->rules( $rules ); Note: Remember to add So, for example, for this $_POST = array(
payment_method => 'credit_card',
credit_card_number => '',
bank_account_alias => 'wrong field is filled out, should be credit_card_number'
); The final rules array passed in to the validator would be: array(2) {
["required"]=> array(2) {
[0]=> string(14) "payment_method"
[1]=> string(18) "credit_card_number"
}
["creditCard"]=> array(1) {
[0]=> string(18) "credit_card_number"
}
} The Thoughts?Id love to hear @vlucas and @willemwollebrants thoughts on this, I'd be happy to work on a PR to implement either a baked in solution or a way to allow custom validation rules to validate empty fields ( That being said, I have no idea if this use case is within the scope of the project or not, I'd argue it is, but I'm willing to be convinced otherwise. |
Uh oh!
There was an error while loading. Please reload this page.
Hello,
I want to validate the "field2" only if "field1" is present and if "field1" value is equal to "myvalue1".
Indeed, "field1" is a radio button and can have three different values : "myvalue1", "myvalue2" and "myvalue3".
Is this question a new feature or can you help me to do this ?
thank you.
The text was updated successfully, but these errors were encountered: