@@ -634,6 +634,101 @@ let you find out which options are defined::
634
634
}
635
635
}
636
636
637
+ Nested Options
638
+ ~~~~~~~~~~~~~~
639
+
640
+ .. versionadded :: 4.2
641
+ The support of nested options 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 a
645
+ closure as the default value of the ``spool `` option with a
646
+ :class: `Symfony\\ Component\\ OptionsResolver\\ OptionsResolver ` argument. Based on
647
+ this instance, you can define the options under ``spool `` and its desired
648
+ default value::
649
+
650
+ class Mailer
651
+ {
652
+ // ...
653
+
654
+ public function configureOptions(OptionsResolver $resolver)
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
+ Nested options also support required options, validation (type, value) and
681
+ normalization of their values. If the default value of a nested option depends
682
+ on another option defined in the parent level, add a second ``Options `` argument
683
+ to the closure to 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
704
+ ``Options `` respectively. Otherwise, the closure itself is considered as the
705
+ default value of the option.
706
+
707
+ In same way, parent options can access to the nested options as normal arrays::
708
+
709
+ class Mailer
710
+ {
711
+ // ...
712
+
713
+ public function configureOptions(OptionsResolver $resolver)
714
+ {
715
+ $resolver->setDefault('spool', function (OptionsResolver $spoolResolver) {
716
+ $spoolResolver->setDefaults(array(
717
+ 'type' => 'file',
718
+ // ...
719
+ ));
720
+ });
721
+ $resolver->setDefault('profiling', function (Options $options) {
722
+ return 'file' === $options['spool']['type'];
723
+ });
724
+ }
725
+ }
726
+
727
+ .. note ::
728
+
729
+ The fact that an option is defined as nested means that you must pass
730
+ an array of values to resolve it at runtime.
731
+
637
732
Deprecating the Option
638
733
~~~~~~~~~~~~~~~~~~~~~~
639
734
0 commit comments