Wednesday, September 12, 2012

Conditional validation using the Symfony2 Validation Component | E-butik Developer Blog

Today we ran in to an issue (or more like an unimplemented enhancement request), where we wanted to do conditional validation.
In our use case, we had a checkbox, which is basically an enable/disable switch. We also had three text inputs, parameters to the feature enabled by the checkbox.
In this case, we wanted the validation of the inputs to depend on whether the switch was enabled.
There are a few ways to do this. You could write your own validator specifically for this purpose. You could write a callback validator, that validates the object. Both these approaches have a big drawback. Even though what all we needed was a conditional NotBlank validator, who knows what we might wish to do in the future with it? We wanted to keep the flexibility of the validation component.
It turns out that’s entirely possible, albeit a bit tricky. To illustrate, let’s imagine a petition. Your form is for entering supporters for a petition. Let’s say that you optionally allow the supporter to enter which city they live in, and that you optionally show that city on a public petition page. Something like this POPO:
Now, of course it wouldn’t be much of a petition if you didn’t require names of the supporters. As for the city, like we’ve said, it’s optional. However, it makes no sense to have the city public unless something is entered.
This can be accomplished using the callback validator, getting the graph walker from the execution context, and validating a separate validation group.
      $ec->getGraphWalker()->walkReference($this, 'public_city_group', $ec->getPropertyPath(), true);

  // Setters, getters etc. are omitted for brevity
This way, the non-grouped assertions are always validated, and the assertions in thepublic_city_group group are validated if is_city_public is true.
Of course, you can have more complex validation rules, and you could also have multiple conditional groups depending on one or more of the instance variables.

More than 3 requests, I'll translate this to Chinese.

No comments: