-
Notifications
You must be signed in to change notification settings - Fork 11.1k
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
[6.x] Add exclude_if validation rule #30835
Conversation
I could see the utility here. How hard would it be to support nested attributes? |
@taylorotwell Less difficult than i thought it would be. The Working example 1: // Post data
{"has_appointments": false, "appointments": ["2019-05-15", "invalid date"]} public function post(Request $request)
{
$data = $request->validate([
'has_appointments' => ['required', 'bool'],
'appointments.*' => ['exclude_if:has_appointments,false', 'required', 'date'],
]);
// $data === ['has_appointments' => false]
} Working example 2: // Post data
{
"has_appointments": false,
"appointments": [
{"date": "2019-05-15", "name": "Bob"},
{"date": "invalid date", "name": "Bob"},
]
} public function post(Request $request)
{
$data = $request->validate([
'has_appointments' => ['required', 'bool'],
'appointments' => ['exclude_if:has_appointments,false', 'required', 'array'],
'appointments.*.date' => ['required', 'date'],
'appointments.*.name' => ['required', 'string'],
]);
// $data === ['has_appointments' => false]
} I tried to write some tests for even deeper nesting, but they were behaving very strangely. It seemed to be completely ignoring validation rules for attributes nested twice. I was either doing something wrong or that is a problem not related to this PR. |
@taylorotwell I think this is ready to merge |
What about this?
|
I'll create a PR in the next few that show off the weird behavior |
This is very useful, but required_if and exclude_if validations is very similar. Why not just change the current behavior of required_if validation rule? |
@SjorsO This is amazing and perfect for an issue I have where a user can optionally make a product rentable. As you say: I have a checkbox in the UI to determine if the product should be available for rent, and then separate inputs for the rental price and period. Thank you for contributing this! |
I think this feature doesn't really fit within validation. It rather seems like it is sanitization of inputs. It might be better to keep those separate. |
Agree completely @spawnia This isn't a validation rule at all, it does no validation, it performs an action. I'm surprised this passed and was included as a validation rule. |
@hrkristian So what about things like |
@martinbean Bail is simply "preceding validation rules decide whether or not ensuing rules are evaluated" In any case I'm not sure why such a comparison is relevant. |
Depending on how you look at it, the In some situations, using For example, with public function post(Request $request, Document $document)
{
$data = $request->validate([
'is_approved' => 'required|bool',
'rejection_reason' => 'exclude_if:is_approved,true|required|string|max:255',
]);
$document->update($data);
} Instead of like this: public function post(Request $request, Document $document)
{
$data = $request->validate([
'is_approved' => 'required|bool',
'rejection_reason' => 'present|nullable|string|max:255',
]);
if (! $data['is_approved']) {
unset($data['rejection_reason']);
}
$document->update($data);
} |
It's a mutator. A mutator doesn't have to mutate data, but that is its purpose. As for your code snippet, what's wrong with it? By adding an "exclude_if", you're introducing data mutation in a place where you wouldn't normally look for it: in a validator. Lastly, I'd just like to add. We program as best we can by best practices and patterns. I realise this is a bit of a harsh "attack", and I don't mean to offend. |
The This has caused users of one of my packages grief - see nuwave/lighthouse#1165 (comment) - because we assumed that Laravel validation is fire-and-forget. I still think it should be. Our solution was to simply tell users not to use those rules. |
The goal of this PR is to make it easy to exclude attributes from a request based on the value of other attributes. This is useful when having to validate data from a form where certain checkboxes hide or show other inputs.
For example, imagine a form with an
has_doctor_appointment
checkbox, that when checked, toggles anappointment_date
anddoctor_name
input. A user can check the checkbox, fill in a date, and then uncheck the checkbox. The date input is no longer visible, but still contains a value. When using Redux Form, even when the input is not visible, the value still gets posted.Usually, you would validate the form above something like this:
The database now contains a record where has_appointment is false, but that has an appointment_date. This is not right. As far as i know, the only way to ensure you never store data like this is by adding statements like this to your controller/validator:
With the exclude_if validation rule, you can validate like this instead:
The idea for this validation rule comes from a project we are working on at the office. It has multiple large forms, that all have many checkboxes that toggle other inputs. The way we solve this now is by making sure the inputs are reset when they are hidden. When they are reset Redux Form doesn't include them in the post data. Making sure the fields are properly reset has been troublesome in the past. This approach also does not prevent users from theoretically posting their own incorrect data to the endpoint.
With this new validation rule, the front-end doesn't have to reset any of the fields, since the back-end can easily exclude values.
This PR is still a work in progress. I would like to get some feedback on it before i spend more time on it.
Todo:
Not tested:
Nested attributes 2+ levels deep (I'm not sure if this is supported at all)