@@ -634,6 +634,100 @@ let you find out which options are defined::
634634 }
635635 }
636636
637+ Nested Option
638+ ~~~~~~~~~~~~~
639+
640+ .. versionadded :: 4.2
641+ This feature was introduced in Symfony 4.2.
642+
643+ Suppose you have an option named ``spool `` which has two sub-options ``type ``
644+ and ``path ``. Instead of defining it as a simple array of values, you can pass
645+ a closure as the default value of the ``spool `` option with a :class: `Symfony\\ Component\\ OptionsResolver\\ OptionsResolver `
646+ argument. Based on this instance, you can define the options under ``spool `` and its desired default
647+ value::
648+
649+ class Mailer
650+ {
651+ // ...
652+
653+ public function configureOptions(OptionsResolver $resolver)
654+ {
655+ $resolver->setDefault('spool', function (OptionsResolver $spoolResolver) {
656+ $spoolResolver->setDefaults(array(
657+ 'type' => 'file',
658+ 'path' => '/path/to/spool',
659+ ));
660+ $spoolResolver->setAllowedValues('type', array('file', 'memory'));
661+ $spoolResolver->setAllowedTypes('path', 'string');
662+ });
663+ }
664+
665+ public function sendMail($from, $to)
666+ {
667+ if ('memory' === $this->options['spool']['type']) {
668+ // ...
669+ }
670+ }
671+ }
672+
673+ $mailer = new Mailer(array(
674+ 'spool' => array(
675+ 'type' => 'memory',
676+ ),
677+ ));
678+
679+ Also you can define required options, validation (type, value) and normalization of these
680+ nested options.
681+
682+ If the default value of a child option depend on another option defined in parent level,
683+ adds a second ``Options `` argument to the closure for access to them::
684+
685+ class Mailer
686+ {
687+ // ...
688+
689+ public function configureOptions(OptionsResolver $resolver)
690+ {
691+ $resolver->setDefault('sandbox', false);
692+ $resolver->setDefault('spool', function (OptionsResolver $spoolResolver, Options $parent) {
693+ $spoolResolver->setDefaults(array(
694+ 'type' => $parent['sandbox'] ? 'memory' : 'file',
695+ // ...
696+ ));
697+ });
698+ }
699+ }
700+
701+ .. caution ::
702+
703+ The arguments of the closure must be type hinted as ``OptionsResolver `` and ``Options `` respectively.
704+ Otherwise, the closure itself is considered as the default value of the option.
705+
706+ In same way, parent options can access to the child option as normal array::
707+
708+ class Mailer
709+ {
710+ // ...
711+
712+ public function configureOptions(OptionsResolver $resolver)
713+ {
714+ $resolver->setDefault('spool', function (OptionsResolver $spoolResolver) {
715+ $spoolResolver->setDefaults(array(
716+ 'type' => 'file',
717+ // ...
718+ ));
719+ });
720+ $resolver->setDefault('profiling', function (Options $options) {
721+ return 'file' === $options['spool']['type'];
722+ });
723+ }
724+ }
725+
726+ .. note ::
727+
728+ The fact that an option is defined as nested means that you must pass
729+ an array of values to resolve it at runtime.
730+
637731Deprecating the Option
638732~~~~~~~~~~~~~~~~~~~~~~
639733
0 commit comments