@@ -634,6 +634,105 @@ 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 want an option named ``spool `` which has two sub-options ``type ``
644+ and ``path ``. Instead of define it as a simple array of values, you can pass
645+ a closure as the default value of the ``spool `` option with an: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+ // ...
650+ class Mailer
651+ {
652+ // ...
653+ public function configureOptions(OptionsResolver $resolver)
654+ {
655+ // ...
656+ $resolver->setDefault('spool', function (OptionsResolver $spoolResolver) {
657+ $spoolResolver->setDefaults(array(
658+ 'type' => 'file',
659+ 'path' => '/path/to/spool',
660+ ));
661+ $spoolResolver->setAllowedValues('type', array('file', 'memory'));
662+ $spoolResolver->setAllowedTypes('path', 'string');
663+ });
664+ }
665+
666+ public function sendMail($from, $to)
667+ {
668+ if ('memory' === $this->options['spool']['type']) {
669+ // ...
670+ }
671+ }
672+ }
673+
674+ $mailer = new Mailer(array(
675+ 'spool' => array(
676+ 'type' => 'memory',
677+ ),
678+ ));
679+
680+ It allows you to create a nested options system with required options, validation (type, value),
681+ normalization and more.
682+
683+ If the default value of a child option depend on another option defined in parent level,
684+ adds a second ``Options `` argument to the closure::
685+
686+ // ...
687+ class Mailer
688+ {
689+ // ...
690+ public function configureOptions(OptionsResolver $resolver)
691+ {
692+ // ...
693+ $resolver->setDefault('sandbox', false);
694+ $resolver->setDefault('spool', function (OptionsResolver $spoolResolver, Options $parent) {
695+ $spoolResolver->setDefaults(array(
696+ 'type' => $parent['sandbox'] ? 'memory' : 'file',
697+ // ...
698+ ));
699+ // ...
700+ });
701+ }
702+ }
703+
704+ ..caution ::
705+
706+ The arguments of the closure must be type hinted as ``OptionsResolver `` and ``Options `` respectively.
707+ Otherwise, the closure itself is considered as the default value of the option.
708+
709+ In same way, parent options can access to the child option as follows::
710+
711+ // ...
712+ class Mailer
713+ {
714+ // ...
715+ public function configureOptions(OptionsResolver $resolver)
716+ {
717+ // ...
718+ $resolver->setDefault('spool', function (OptionsResolver $spoolResolver) {
719+ $spoolResolver->setDefaults(array(
720+ 'type' => 'file',
721+ // ...
722+ ));
723+ // ...
724+ });
725+ $resolver->setDefault('profiling', function (Options $options) {
726+ return 'file' === $options['spool']['type'];
727+ });
728+ }
729+ }
730+
731+ ..note ::
732+
733+ The fact that an option is defined as nested, means that you must to pass
734+ an array of values to resolver on runtime.
735+
637736Deprecating the Option
638737~~~~~~~~~~~~~~~~~~~~~~
639738