8000 Documenting Abstract Bundle and Extension · symfony/symfony-docs@426e289 · GitHub
[go: up one dir, main page]

Skip to content

Commit 426e289

Browse files
committed
Documenting Abstract Bundle and Extension
1 parent c2b642b commit 426e289

File tree

6 files changed

+261
-44
lines changed

6 files changed

+261
-44
lines changed

bundles.rst

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -48,33 +48,52 @@ The new bundle is called AcmeTestBundle, where the ``Acme`` portion is an exampl
4848
name that should be replaced by some "vendor" name that represents you or your
4949
organization (e.g. ABCTestBundle for some company named ``ABC``).
5050

51-
Start by creating a ``src/Acme/TestBundle/`` directory and adding a new file
51+
Start by creating a ``Acme/TestBundle/src/`` directory and adding a new file
5252
called ``AcmeTestBundle.php``::
5353

54-
// src/Acme/TestBundle/AcmeTestBundle.php
55-
namespace App\Acme\TestBundle;
54+
// Acme/TestBundle/src/AcmeTestBundle.php
55+
namespace Acme\TestBundle;
5656

57-
use Symfony\Component\HttpKernel\Bundle\Bundle;
57+
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
5858

59-
class AcmeTestBundle extends Bundle
59+
class AcmeTestBundle extends AbstractBundle
6060
{
6161
}
6262

63+
.. versionadded:: 6.1
64+
65+
The ``AbstractBundle`` was introduced in Symfony 6.1. If your bundle must be compatible
66+
with previous Symfony versions you have to extend from the :class:`Symfony\\Component\\HttpKernel\\Bundle\\Bundle`
67+
instead.
68+
6369
.. tip::
6470

6571
The name AcmeTestBundle follows the standard
6672
:ref:`Bundle naming conventions <bundles-naming-conventions>`. You could
6773
also choose to shorten the name of the bundle to simply TestBundle by naming
6874
this class TestBundle (and naming the file ``TestBundle.php``).
6975

70-
This empty class is the only piece you need to create the new bundle. Though
76+
It's recommended to place your bundle class in the ``src/`` directory and keep out all the
77+
configuration files, templates, translations, etc. By default, Symfony determines the bundle path from the
78+
directory where the bundle class is placed, so you have to define the :method:`Symfony\\Component\\HttpKernel\\Bundle\\Bundle::getPath`
79+
method to tell Symfony what is the root directory of your bundle path::
80+
81+
class AcmeTestBundle extends AbstractBundle
82+
{
83+
public function getPath(): string
84+
{
85+
return \dirname(__DIR__);
86+
}
87+
}
88+
89+
This almost empty class is the only piece you need to create the new bundle. Though
7190
commonly empty, this class is powerful and can be used to customize the behavior
7291
of the bundle. Now that you've created the bundle, enable it::
7392

7493
// config/bundles.php
7594
return [
7695
// ...
77-
App\Acme\TestBundle\AcmeTestBundle::class => ['all' => true],
96+
Acme\TestBundle\AcmeTestBundle::class => ['all' => true],
7897
];
7998

8099
And while it doesn't do anything yet, AcmeTestBundle is now ready to be used.
@@ -86,26 +105,24 @@ The directory structure of a bundle is meant to help to keep code consistent
86105
between all Symfony bundles. It follows a set of conventions, but is flexible
87106
to be adjusted if needed:
88107

89-
``Controller/``
108+
``src/Controller/``
90109
Contains the controllers of the bundle (e.g. ``RandomController.php``).
91110

92-
``DependencyInjection/``
93-
Holds certain Dependency Injection Extension classes, which may import service
94-
configuration, register compiler passes or more (this directory is not
95-
necessary).
96-
97-
``Resources/config/``
111+
``config/``
98112
Houses configuration, including routing configuration (e.g. ``routing.yaml``).
99113

100-
``Resources/views/``
101-
Holds templates organized by controller name (e.g. ``Random/index.html.twig``).
114+
``templates/``
115+
Holds templates organized by controller name (e.g. ``random/index.html.twig``).
116+
117+
``translations/``
118+
Holds translations organized by domain and locale (e.g. ``AcmeTestBundle.en.xlf``).
102119

103-
``Resources/public/``
120+
``public/``
104121
Contains web assets (images, stylesheets, etc) and is copied or symbolically
105122
linked into the project ``public/`` directory via the ``assets:install`` console
106123
command.
107124

108-
``Tests/``
125+
``tests/``
109126
Holds all tests for the bundle.
110127

111128
A bundle can be as small or large as the feature it implements. It contains

bundles/configuration.rst

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,57 @@ Assuming the XSD file is called ``hello-1.0.xsd``, the schema location will be
431431
<!-- ... -->
432432
</container>
433433
434+
Defining Configuration directly in your Bundle class
435+
----------------------------------------------------
436+
437+
.. versionadded:: 6.1
438+
439+
The ``AbstractBundle`` class is introduced in Symfony 6.1.
440+
441+
As another option, you can define the extension configuration directly in your Bundle
442+
class by implementing :class:`Symfony\\Component\\Config\\Definition\\ConfigurableInterface`,
443+
which is already supported when your bundle extend from the :class:`Symfony\\Component\\HttpKernel\\Bundle\\AbstractBundle`::
444+
445+
use Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
446+
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
447+
448+
class AcmeFooBundle extends AbstractBundle
449+
{
450+
public function configure(DefinitionConfigurator $definition): void
451+
{
452+
// loads config definition from a file
453+
$definition->import('../config/definition.php');
454+
455+
// loads config definition from multiple files (when it's too long you can split it)
456+
$definition->import('../config/definition/*.php');
457+
458+
// if the configuration is short, consider adding it in this class
459+
$definition->rootNode()
460+
->children()
461+
->scalarNode('foo')->defaultValue('bar')->end()
462+
->end()
463+
;
464+
}
465+
}
466+
467+
This method is a shortcut of the previous "Extension", "Configuration" and "TreeBuilder" convention,
468+
where you also have the possibility to import configuration definition from an external file::
469+
470+
// Acme/FooBundle/config/definition.php
471+
use Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
472+
473+
return static function (DefinitionConfigurator $definition) {
474+
$definition->rootNode()
475+
->children()
476+
->scalarNode('foo')->defaultValue('bar')->end()
477+
->end()
478+
;
479+
};
480+
481+
.. note::
482+
483+
The "configure()" method is called only at compiler time.
484+
434485
.. _`FrameworkBundle Configuration`: https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
435486
.. _`TwigBundle Configuration`: https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php
436487
.. _`XML namespace`: https://en.wikipedia.org/wiki/XML_namespace

bundles/extension.rst

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,44 @@ the full classmap executing the ``dump-autoload`` command of Composer.
147147
This technique can't be used when the classes to compile use the ``__DIR__``
148148
or ``__FILE__`` constants, because their values will change when loading
149149
these classes from the ``classes.php`` file.
150+
151+
Loading Services directly in your Bundle class
152+
----------------------------------------------
153+
154+
.. versionadded:: 6.1
155+
156+
The ``AbstractBundle`` class is introduced in Symfony 6.1.
157+
158+
Alternatively, you can define and load services configuration directly in a bundle class
159+
by extending from the :class:`Symfony\\Component\\HttpKernel\\Bundle\\AbstractBundle`
160+
and defining the :method:`Symfony\\Component\\HttpKernel\\Bundle\\AbstractBundle::loadExtension` method::
161+
162+
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
163+
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
164+
165+
class AcmeFooBundle extends AbstractBundle
166+
{
167+
public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
168+
{
169+
$container->parameters()
170+
->set('foo', $config['foo']);
171+
172+
$container->import('../config/services.php');
173+
174+
if ('bar' === $config['foo']) {
175+
$container->services()
176+
->set(Parser::class);
177+
}
178+
}
179+
}
180+
181+
This method is a shortcut of the previous "load()" method, but with more options
182+
to define and import the service configuration with less effort. The ``$config``
183+
argument is the previous ``$configs`` array but already merged and processed. And
184+
through the ``$container`` configurator you can import the services configuration
185+
from an external file in any supported format (php, yaml, xml) or simply define
186+
them in place using the fluent interfaces.
187+
188+
.. note::
189+
190+
The "loadExtension()" like "load()" method is called only at compiler time.

bundles/override.rst

Lines changed: 9 additions & 9 deletions
@@ -173,7 +173,7 @@ For this reason, you can override any bundle translation file from the main
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ features of a bundle.
1212

1313
The bundle overriding mechanism means that you cannot use physical paths to
1414
refer to bundle's resources (e.g. ``__DIR__/config/services.xml``). Always
15-
use logical paths in your bundles (e.g. ``@FooBundle/Resources/config/services.xml``)
15+
use logical paths in your bundles (e.g. ``@FooBundle/config/services.xml``)
1616
and call the :ref:`locateResource() method <http-kernel-resource-locator>`
1717
to turn them into physical paths when needed.
1818

@@ -23,12 +23,12 @@ Templates
2323

2424
Third-party bundle templates can be overridden in the
2525
``<your-project>/templates/bundles/<bundle-name>/`` directory. The new templates
26-
must use the same name and path (relative to ``<bundle>/Resources/views/``) as
26+
must use the same name and path (relative to ``<bundle>/templates/``) as
2727
the original templates.
2828

29-
For example, to override the ``Resources/views/Registration/confirmed.html.twig``
30-
template from the FOSUserBundle, create this template:
31-
``<your-project>/templates/bundles/FOSUserBundle/Registration/confirmed.html.twig``
29+
For example, to override the ``templates/registration/confirmed.html.twig``
30+
template from the AcmeUserBundle, create this template:
31+
``<your-project>/templates/bundles/AcmeUserBundle/registration/confirmed.html.twig``
3232

3333
.. caution::
3434

@@ -43,9 +43,9 @@ extend from the original template, not from the overridden one:
4343

4444
.. code-block:: twig
4545
46-
{# templates/bundles/FOSUserBundle/Registration/confirmed.html.twig #}
46+
{# templates/bundles/AcmeUserBundle/registration/confirmed.html.twig #}
4747
{# the special '!' prefix avoids errors when extending from an overridden template #}
48-
{% extends "@!FOSUser/Registration/confirmed.html.twig" %}
48+
{% extends "@!AcmeUser/registration/confirmed.html.twig" %}
4949
5050
{% block some_block %}
5151
...
173173
``translations/`` directory, as long as the new file uses the same domain.
174174

175175
For example, to override the translations defined in the
176-
``Resources/translations/FOSUserBundle.es.yml`` file of the FOSUserBundle,
177-
create a ``<your-project>/translations/FOSUserBundle.es.yml`` file.
176+
``translations/AcmeUserBundle.es.yaml`` file of the AcmeUserBundle,
177+
create a ``<your-project>/translations/AcmeUserBundle.es.yaml`` file.
178178

179179
.. _`the Doctrine documentation`: https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/inheritance-mapping.html#overrides

bundles/prepend_extension.rst

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,44 @@ More than one Bundle using PrependExtensionInterface
157157
If there is more than one bundle that prepends the same extension and defines
158158
the same key, the bundle that is registered **first** will take priority:
159159
next bundles won't override this specific config setting.
160+
161+
Prepending Extension directly in your Bundle class
162+
--------------------------------------------------
163+
164+
.. versionadded:: 6.1
165+
166+
The ``AbstractBundle`` class is introduced in Symfony 6.1.
167+
168+
By preference, you can append or prepend extension configuration directly in your Bundle
169+
class for any bundle by extending from the :class:`Symfony\\Component\\HttpKernel\\Bundle\\AbstractBundle`
170+
and defining the :method:`Symfony\\Component\\HttpKernel\\Bundle\\AbstractBundle::prependExtension` method::
171+
172+
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
173+
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
174+
175+
class FooBundle extends AbstractBundle
176+
{
177+
public function prependExtension(ContainerConfigurator $container, ContainerBuilder $builder): void
178+
{
179+
// prepend
180+
$builder->prependExtensionConfig('framework', [
181+
'cache' => ['prefix_seed' => 'foo/bar'],
182+
]);
183+
184+
// append
185+
$container->extension('framework', [
186+
'cache' => ['prefix_seed' => 'foo/bar'],
187+
])
188+
189+
// append from file
190+
$container->import('../config/packages/cache.php');
191+
}
192+
}
193+
194+
This method is a shortcut of the previous "PrependExtensionInterface::prepend" method,
195+
allowing you also to import and append extension config from an external file in one of
196+
the supported formats (php, yaml, xml).
197+
198+
.. note::
199+
200+
The "prependExtension()" like "prepend()" method is called only at compiler time.

0 commit comments

Comments
 (0)
0