@@ -46,11 +46,114 @@ as integration of other related components:
4646 $framework->form()->enabled(true);
4747 };
4848
49+ There are two different ways of creating friendly configuration for a bundle:
50+
51+ #. :ref: `Using the main bundle class <bundle-friendly-config-bundle-class >`:
52+ this is recommended for new bundles and for bundles following the
53+ :ref: `recommended directory structure <bundles-directory-structure >`;
54+ #. :ref: `Using the Bundle extension class <bundle-friendly-config-extension >`:
55+ this was the traditional way of doing it, but nowadays it's only recommended for
56+ bundles following the :ref: `legacy directory structure <bundles-legacy-directory-structure >`.
57+
58+ .. _using-the-bundle-class :
59+ .. _bundle-friendly-config-bundle-class :
60+
61+ Using the AbstractBundle Class
62+ ------------------------------
63+
64+ .. versionadded :: 6.1
65+
66+ The ``AbstractBundle `` class was introduced in Symfony 6.1.
67+
68+ In bundles extending the :class: `Symfony\\ Component\\ HttpKernel\\ Bundle\\ AbstractBundle `
69+ class, you can add all the logic related to processing the configuration in that class::
70+
71+ // src/AcmeSocialBundle.php
72+ namespace Acme\SocialBundle;
73+
74+ use Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
75+ use Symfony\Component\DependencyInjection\ContainerBuilder;
76+ use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
77+ use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
78+
79+ class AcmeSocialBundle extends AbstractBundle
80+ {
81+ public function configure(DefinitionConfigurator $definition): void
82+ {
83+ $definition->rootNode()
84+ ->children()
85+ ->arrayNode('twitter')
86+ ->children()
87+ ->integerNode('client_id')->end()
88+ ->scalarNode('client_secret')->end()
89+ ->end()
90+ ->end() // twitter
91+ ->end()
92+ ;
93+ }
94+
95+ public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
96+ {
97+ // the "$config" variable is already merged and processed so you can
98+ // use it directly to configure the service container (when defining an
99+ // extension class, you also have to do this merging and processing)
100+ $containerConfigurator->services()
101+ ->get('acme.social.twitter_client')
102+ ->arg(0, $config['twitter']['client_id'])
103+ ->arg(1, $config['twitter']['client_secret'])
104+ ;
105+ }
106+ }
107+
108+ .. note ::
109+
110+ The ``configure() `` and ``loadExtension() `` methods are called only at compile time.
111+
112+ .. tip ::
113+
114+ The ``AbstractBundle::configure() `` method also allows to import the
115+ configuration definition from one or more files::
116+
117+ // src/AcmeSocialBundle.php
118+ namespace Acme\SocialBundle;
119+
120+ // ...
121+ class AcmeSocialBundle extends AbstractBundle
122+ {
123+ public function configure(DefinitionConfigurator $definition): void
124+ {
125+ $definition->import('../config/definition.php');
126+ // you can also use glob patterns
127+ //$definition->import('../config/definition/*.php');
128+ }
129+
130+ // ...
131+ }
132+
133+ .. code-block :: php
134+
135+ // config/definition.php
136+ use Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
137+
138+ return static function (DefinitionConfigurator $definition): void {
139+ $definition->rootNode()
140+ ->children()
141+ ->scalarNode('foo')->defaultValue('bar')->end()
142+ ->end()
143+ ;
144+ };
145+
146+ .. _bundle-friendly-config-extension :
147+
49148Using the Bundle Extension
50149--------------------------
51150
151+ This is the traditional way of creating friendly configuration for bundles. For new
152+ bundles it's recommended to :ref: `use the main bundle class <bundle-friendly-config-bundle-class >`,
153+ but the traditional way of creating an extension class still works.
154+
52155Imagine you are creating a new bundle - AcmeSocialBundle - which provides
53- integration with Twitter. To make your bundle configurable to the user, you
156+ integration with X/ Twitter. To make your bundle configurable to the user, you
54157can add some configuration that looks like this:
55158
56159.. configuration-block ::
@@ -110,7 +213,7 @@ load correct services and parameters inside an "Extension" class.
110213
111214 If a bundle provides an Extension class, then you should *not * generally
112215 override any service container parameters from that bundle. The idea
113- is that if an Extension class is present, every setting that should be
216+ is that if an extension class is present, every setting that should be
114217 configurable should be present in the configuration made available by
115218 that class. In other words, the extension class defines all the public
116219 configuration settings for which backward compatibility will be maintained.
@@ -315,90 +418,6 @@ In your extension, you can load this and dynamically set its arguments::
315418 // ... now use the flat $config array
316419 }
317420
318- .. _using-the-bundle-class :
319-
320- Using the AbstractBundle Class
321- ------------------------------
322-
323- As an alternative, instead of creating an extension and configuration class as
324- shown in the previous section, you can also extend
325- :class: `Symfony\\ Component\\ HttpKernel\\ Bundle\\ AbstractBundle ` to add this
326- logic to the bundle class directly::
327-
328- // src/AcmeSocialBundle.php
329- namespace Acme\SocialBundle;
330-
331- use Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
332- use Symfony\Component\DependencyInjection\ContainerBuilder;
333- use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
334- use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
335-
336- class AcmeSocialBundle extends AbstractBundle
337- {
338- public function configure(DefinitionConfigurator $definition): void
339- {
340- $definition->rootNode()
341- ->children()
342- ->arrayNode('twitter')
343- ->children()
344- ->integerNode('client_id')->end()
345- ->scalarNode('client_secret')->end()
346- ->end()
347- ->end() // twitter
348- ->end()
349- ;
350- }
351-
352- public function loadExtension(array $config, ContainerConfigurator $containerConfigurator, ContainerBuilder $containerBuilder): void
353- {
354- // Contrary to the Extension class, the "$config" variable is already merged
355- // and processed. You can use it directly to configure the service container.
356- $containerConfigurator->services()
357- ->get('acme.social.twitter_client')
358- ->arg(0, $config['twitter']['client_id'])
359- ->arg(1, $config['twitter']['client_secret'])
360- ;
361- }
362- }
363-
364- .. note ::
365-
366- The ``configure() `` and ``loadExtension() `` methods are called only at compile time.
367-
368- .. tip ::
369-
370- The ``AbstractBundle::configure() `` method also allows to import the
371- configuration definition from one or more files::
372-
373- // src/AcmeSocialBundle.php
374- namespace Acme\SocialBundle;
375-
376- // ...
377- class AcmeSocialBundle extends AbstractBundle
378- {
379- public function configure(DefinitionConfigurator $definition): void
380- {
381- $definition->import('../config/definition.php');
382- // you can also use glob patterns
383- //$definition->import('../config/definition/*.php');
384- }
385-
386- // ...
387- }
388-
389- .. code-block :: php
390-
391- // config/definition.php
392- use Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
393-
394- return static function (DefinitionConfigurator $definition): void {
395- $definition->rootNode()
396- ->children()
397- ->scalarNode('foo')->defaultValue('bar')->end()
398- ->end()
399- ;
400- };
401-
402421Modifying the Configuration of Another Bundle
403422---------------------------------------------
404423
0 commit comments