In Symfony 2.8, in a custom form type, is it possible to make setAllowedValues return a result that depends on the value of another option? There isn't an obvious way to access an Options
object in the closure as far as I can see.
public function configureOptions(OptionsResolver $resolver) {
$resolver->setRequired('option1');
$resolver->setRequired('option2');
$resolver->setAllowedValues('option2', function ($value) {
return $based_on_set_restricted_by_option1; // <-- option2 values are allowed or denied depending on what option1 says
}
}
The closest idea to a solution that I have is to have an option that is a dictionary that encapsulates both option1 and option2 and do setAllowedValues on it instead, but it's not easy to restructure the options right now.
The method configureOptions()
of symfony form type can do many things as it provides an OptionsResolver object (relying on its own component see) to tune your configuration.
What you need in that case is to call $resolver->setNormalizer()
(see) which does exactly what you want, it takes an option to define once the others are set and a callable.
When the resolver normalizes your option it executes the callable by passing an array of all options as the first argument, and the set value of the option to normalize as a second argument :
// class CustomFormType extends \Symfony\Component\Form\Extension\Core\Type\AbstractType
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('some_option', 'default value');
// or many at once
$resolver->setDefaults(array(
'some_option' => 0,
'range_condition' => null,
);
// what you need
$someOptionNormalizer = function (Options $options, $someOption) {
$rangeCondition = $options['range_condition'];
if (in_array($rangeCondition, range(2, 5))) {
if (in_array($someOption, range(6, 9))) {
return $someOption;
}
throw new InvalidOptionsException(sprintf('When "range_condition" is inferior or equal to 5, "some_option" should be between 6 and 9, but "%d" given.', $someOption));
}
if (in_array($rangeCondition, range(10, 13))) {
if (in_array($someOption, range(1000, 1005))) {
return $someOption;
}
throw new InvalidOptionsException(sprintf('When "range_condition" is between 10 and 13, "some_option" should be between 1000 and 1005, but "%d" given.', $someOption));
}
};
$resolver->setNormalizer('some_option', $someOptionNormalizer);
// you can also do
$resolver->setRequired('some_option');
$resolver->setAllowedTypes('some_option', array('integer'));
$resolver->setAllowedTypes('range_condition', array('null', 'integer'));
$resolver->setAllowedValues('some_option', array_merge(range(6, 9), range(1000, 1005)));
$resolver->setAllowedValues('range_condition', array_merge(range(2, 5), range(10, 13)));
// ...
}
来源:https://stackoverflow.com/questions/35204850/define-a-form-option-allowed-values-depending-on-another-option-value-in-a-formt