@@ -634,6 +634,100 @@ let you find out which options are defined::
634
634
}
635
635
}
636
636
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
+
637
731
Deprecating the Option
638
732
~~~~~~~~~~~~~~~~~~~~~~
639
733
0 commit comments