FrameworkBundle is the glue between Symfony components and Symfony applications. Over the years, we used it to define the configuration and services of most components. This caused some issues:
- Adding a feature to a component (e.g. a new mailer option) required changes in both the component and FrameworkBundle;
- Some sections depended on others in non-obvious ways (e.g. enabling forms also enabled validation);
- Config files had an unneeded root level (e.g. the config in
config/packages/mailer.yamlstarts withframework:).
In Symfony 8.2, each component ships its own bundle with its configuration,
its services and the classes related to them. There are 29 new bundles such
as CacheBundle, HttpClientBundle, MailerBundle, MessengerBundle, etc.
What This Means for Your Applications
You don't have to change anything. The new bundles are registered
automatically when their component is installed, so there's nothing to add to
config/bundles.php. Thanks to a new configuration aliasing feature, all your
existing framework.* keys (framework.mailer, framework.messenger,
etc.) keep working exactly as before and nothing is deprecated.
However, if you prefer, you can now remove the framework level from these
config files:
1 2 3 4 5 6
# config/packages/mailer.yaml
- framework:
- mailer:
- dsn: '%env(MAILER_DSN)%'
+ mailer:
+ dsn: '%env(MAILER_DSN)%'
The same works in PHP config files:
1 2 3 4 5 6 7 8
// config/packages/mailer.php
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
return App::config([
'mailer' => [
'dsn' => env('MAILER_DSN'),
],
]);
Most keys keep their name at the root level, except these: framework.assets
is now asset, framework.translator is now translation and
framework.workflows is now workflow.
The lock and semaphore keys also accept a DSN directly, as a shortcut
for their resources option (before, a string value at the root level was
silently ignored):
1 2
# config/packages/lock.yaml
lock: '%env(LOCK_DSN)%'
Other minor changes you might notice:
debug:config framework mailerno longer works; usedebug:config mailerinstead;- Enabling forms no longer enables validation automatically; installing
symfony/validatordoes; - Some classes moved from FrameworkBundle to their components and the old ones
are deprecated. The ones you are most likely to use in your apps are
RedirectController(now in the Routing component),TemplateController(now in TwigBundle),AsRoutingConditionService(now in the Routing component) andRouteLoaderInterface(replaced by the#[AsRouteLoader]attribute of the Routing component).
Registering 29 more bundles doesn't slow down your apps. Most of these bundles are only needed when compiling the container, so in production Symfony no longer creates their objects on each request (it only does it when some code asks for them).
New Config Features for Bundle Authors
This work required some new features in the Config component that you can
also use in your own bundles. The aliasOf() method makes a root-level node
forward its value to the configuration of another extension. This is how
framework.workflows keeps working while the Workflow component now owns
the workflow configuration:
1 2 3 4
$rootNode
->children()
->variableNode('workflows')->aliasOf('workflow')->end()
->end();
The new appendFromCallback() method lets you append several nodes from a
callback without breaking the fluent chain of the tree builder. This is useful
when the same group of options is repeated in different parts of your config:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
$rootNode
->children()
->arrayNode('default_options')
->children()
->appendFromCallback($this->addCommonOptions(...))
->end()
->end()
->end();
// ...
private function addCommonOptions(NodeBuilder $builder): void
{
$builder
->integerNode('max_redirects')->end()
->scalarNode('http_version')->end()
;
}