@@ -634,6 +634,105 @@ 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 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 resolve it on runtime.
735
+
637
736
Deprecating the Option
638
737
~~~~~~~~~~~~~~~~~~~~~~
639
738
0 commit comments