Skip to content
  • About
    • What is Symfony?
    • Community
    • News
    • Contributing
    • Support
  • Documentation
    • Symfony Docs
    • Symfony Book
    • Screencasts
    • Symfony Bundles
    • Symfony Cloud
    • Training
  • Services
    • Platform.sh for Symfony Best platform to deploy Symfony apps
    • SymfonyInsight Automatic quality checks for your apps
    • Symfony Certification Prove your knowledge and boost your career
    • SensioLabs Professional services to help you with Symfony
    • Blackfire Profile and monitor performance of your apps
  • Other
  • Blog
  • Download
sponsored by
  1. Home
  2. Documentation
  3. Bundles
  4. How to Load Service Configuration inside a Bundle

How to Load Service Configuration inside a Bundle

Edit this page

Services created by bundles are not defined in the main config/services.yaml file used by the application but in the bundles themselves. This article explains how to create and load service files using the bundle directory structure.

There are two different ways of doing it:

  1. Load your services in the main bundle class: this is recommended for new bundles and for bundles following the recommended directory structure;
  2. Create an extension class to load the service configuration files: this was the traditional way of doing it, but nowadays it's only recommended for bundles following the legacy directory structure.

Loading Services Directly in your Bundle Class

In bundles extending the AbstractBundle class, you can define the loadExtension() method to load service definitions from configuration files:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// ...
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;

class AcmeHelloBundle extends AbstractBundle
{
    public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
    {
        // load an XML, PHP or YAML file
        $container->import('../config/services.xml');

        // you can also add or replace parameters and services
        $container->parameters()
            ->set('acme_hello.phrase', $config['phrase'])
        ;

        if ($config['scream']) {
            $container->services()
                ->get('acme_hello.printer')
                    ->class(ScreamingPrinter::class)
            ;
        }
    }
}

This method works similar to the Extension::load() method explained below, but it uses a new simpler API to define and import service configuration.

Note

Contrary to the $configs parameter in Extension::load(), the $config parameter is already merged and processed by the AbstractBundle.

Note

The loadExtension() is called only at compile time.

Creating an Extension Class

This is the traditional way of loading service definitions in bundles. For new bundles it's recommended to load your services in the main bundle class, but the traditional way of creating an extension class still works.

A dependency injection extension is defined as a class that follows these conventions (later you'll learn how to skip them if needed):

  • It has to live in the DependencyInjection namespace of the bundle;
  • It has to implement the ExtensionInterface, which is usually achieved by extending the Extension class;
  • The name is equal to the bundle name with the Bundle suffix replaced by Extension (e.g. the extension class of the AcmeBundle would be called AcmeExtension and the one for AcmeHelloBundle would be called AcmeHelloExtension).

This is how the extension of an AcmeHelloBundle should look like:

1
2
3
4
5
6
7
8
9
10
11
12
13
// src/DependencyInjection/AcmeHelloExtension.php
namespace Acme\HelloBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;

class AcmeHelloExtension extends Extension
{
    public function load(array $configs, ContainerBuilder $container): void
    {
        // ... you'll load the files here later
    }
}

Manually Registering an Extension Class

When not following the conventions, you will have to manually register your extension. To do this, you should override the Bundle::getContainerExtension() method to return the instance of the extension:

1
2
3
4
5
6
7
8
9
10
11
// ...
use Acme\HelloBundle\DependencyInjection\UnconventionalExtensionClass;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;

class AcmeHelloBundle extends Bundle
{
    public function getContainerExtension(): ?ExtensionInterface
    {
        return new UnconventionalExtensionClass();
    }
}

In addition, when the new Extension class name doesn't follow the naming conventions, you must also override the Extension::getAlias() method to return the correct DI alias. The DI alias is the name used to refer to the bundle in the container (e.g. in the config/packages/ files). By default, this is done by removing the Extension suffix and converting the class name to underscores (e.g. AcmeHelloExtension's DI alias is acme_hello).

Using the load() Method

In the load() method, all services and parameters related to this extension will be loaded. This method doesn't get the actual container instance, but a copy. This container only has the parameters from the actual container. After loading the services and parameters, the copy will be merged into the actual container, to ensure all services and parameters are also added to the actual container.

In the load() method, you can use PHP code to register service definitions, but it is more common if you put these definitions in a configuration file (using the YAML, XML or PHP format).

For instance, assume you have a file called services.xml in the config/ directory of your bundle, your load() method looks like:

1
2
3
4
5
6
7
8
9
10
11
12
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;

// ...
public function load(array $configs, ContainerBuilder $container): void
{
    $loader = new XmlFileLoader(
        $container,
        new FileLocator(__DIR__.'/../../config')
    );
    $loader->load('services.xml');
}

The other available loaders are YamlFileLoader and PhpFileLoader.

Using Configuration to Change the Services

The Extension is also the class that handles the configuration for that particular bundle (e.g. the configuration in config/packages/<bundle_alias>.yaml). To read more about it, see the "How to Create Friendly Configuration for a Bundle" article.

Adding Classes to Compile

Bundles can hint Symfony about which of their classes contain annotations so they are compiled when generating the application cache to improve the overall performance. Define the list of annotated classes to compile in the addAnnotatedClassesToCompile() method:

1
2
3
4
5
6
7
8
9
10
11
12
13
public function load(array $configs, ContainerBuilder $container): void
{
    // ...

    $this->addAnnotatedClassesToCompile([
        // you can define the fully qualified class names...
        'Acme\\BlogBundle\\Controller\\AuthorController',
        // ... but glob patterns are also supported:
        'Acme\\BlogBundle\\Form\\**',

        // ...
    ]);
}

Note

If some class extends from other classes, all its parents are automatically included in the list of classes to compile.

Patterns are transformed into the actual class namespaces using the classmap generated by Composer. Therefore, before using these patterns, you must generate the full classmap executing the dump-autoload command of Composer.

Caution

This technique can't be used when the classes to compile use the __DIR__ or __FILE__ constants, because their values will change when loading these classes from the classes.php file.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
TOC
    Version

    Symfony 7.1 is backed by

    Code consumes server resources. Blackfire tells you how

    Code consumes server resources. Blackfire tells you how

    Be safe against critical risks to your projects and businesses

    Be safe against critical risks to your projects and businesses

    Version:

    Table of Contents

    • Loading Services Directly in your Bundle Class
    • Creating an Extension Class
      • Manually Registering an Extension Class
      • Using the load() Method
      • Using Configuration to Change the Services
    • Adding Classes to Compile

    Symfony footer

    Avatar of zenmate, a Symfony contributor

    Thanks zenmate for being a Symfony contributor

    2 commits • 186 lines changed

    View all contributors that help us make Symfony

    Become a Symfony contributor

    Be an active part of the community and contribute ideas, code and bug fixes. Both experts and newcomers are welcome.

    Learn how to contribute

    Symfony™ is a trademark of Symfony SAS. All rights reserved.

    • What is Symfony?

      • What is Symfony?
      • Symfony at a Glance
      • Symfony Components
      • Symfony Releases
      • Security Policy
      • Logo & Screenshots
      • Trademark & Licenses
      • symfony1 Legacy
    • Learn Symfony

      • Symfony Docs
      • Symfony Book
      • Reference
      • Bundles
      • Best Practices
      • Training
      • eLearning Platform
      • Certification
    • Screencasts

      • Learn Symfony
      • Learn PHP
      • Learn JavaScript
      • Learn Drupal
      • Learn RESTful APIs
    • Community

      • Symfony Community
      • SymfonyConnect
      • Events & Meetups
      • Projects using Symfony
      • Contributors
      • Symfony Jobs
      • Backers
      • Code of Conduct
      • Downloads Stats
      • Support
    • Blog

      • All Blog Posts
      • A Week of Symfony
      • Case Studies
      • Cloud
      • Community
      • Conferences
      • Diversity
      • Living on the edge
      • Releases
      • Security Advisories
      • Symfony Insight
      • Twig
      • SensioLabs Blog
    • Services

      • SensioLabs services
      • Train developers
      • Manage your project quality
      • Improve your project performance
      • Host Symfony projects

      Powered by

    Follow Symfony