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 SensioLabs
  1. Home
  2. Documentation
  3. Bundles
  4. How to Load Service Configuration inside a Bundle
  • Documentation
  • Book
  • Reference
  • Bundles
  • Cloud

Table of Contents

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

How to Load Service Configuration inside a Bundle

Edit this page

Warning: You are browsing the documentation for Symfony 3.3, which is no longer maintained.

Read the updated version of this page for Symfony 6.3 (the current stable version).

How to Load Service Configuration inside a Bundle

In Symfony, you'll find yourself using many services. These services can be registered in the app/config/ directory of your application. But when you want to decouple the bundle for use in other projects, you want to include the service configuration in the bundle itself. This article will teach you how to do that.

Creating an Extension Class

In order to load service configuration, you have to create a Dependency Injection (DI) Extension for your bundle. This class has some conventions in order to be detected automatically. But you'll later see how you can change it to your own preferences. By default, the Extension has to comply with the following conventions:

  • It has to live in the DependencyInjection namespace of the bundle;
  • The name is equal to the bundle name with the Bundle suffix replaced by Extension (e.g. the Extension class of the AppBundle would be called AppExtension and the one for AcmeHelloBundle would be called AcmeHelloExtension).

The Extension class should implement the ExtensionInterface, but usually you would simply extend the Extension class:

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

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

class AcmeHelloExtension extends Extension
{
    public function load(array $configs, ContainerBuilder $container)
    {
        // ... 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
// ...
use Acme\HelloBundle\DependencyInjection\UnconventionalExtensionClass;

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

Since the new Extension class name doesn't follow the naming conventions, you should also override Extension::getAlias() 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 app/config/config.yml file). 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). Luckily, you can use the file loaders in the extension!

For instance, assume you have a file called services.xml in the Resources/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\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\Config\FileLocator;

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

Other available loaders are the YamlFileLoader, PhpFileLoader and IniFileLoader.

Note

The IniFileLoader can only be used to load parameters and it can only load them as strings.

Caution

If you removed the default file with service definitions (i.e. app/config/services.yml), make sure to also remove it from the imports key in app/config/config.yml.

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 app/config/config.yml). To read more about it, see the "How to Create Friendly Configuration for a Bundle" article.

Adding Classes to Compile

3.3

This technique is discouraged and the addClassesToCompile() method was deprecated in Symfony 3.3 because modern PHP versions make it unnecessary.

Symfony creates a big classes.php file in the cache directory to aggregate the contents of the PHP classes that are used in every request. This reduces the I/O operations and increases the application performance.

3.2

The addAnnotatedClassesToCompile() method was added in Symfony 3.2.

Your bundles can also add their own classes into this file thanks to the addClassesToCompile() and addAnnotatedClassesToCompile() methods (both work in the same way, but the second one is for classes that contain PHP annotations). Define the classes to compile as an array of their fully qualified class names:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
use AppBundle\Manager\UserManager;
use AppBundle\Utils\Slugger;

// ...
public function load(array $configs, ContainerBuilder $container)
{
    // ...

    // this method can't compile classes that contain PHP annotations
    $this->addClassesToCompile(array(
        UserManager::class,
        Slugger::class,
        // ...
    ));

    // add here only classes that contain PHP annotations
    $this->addAnnotatedClassesToCompile(array(
        'AppBundle\\Controller\\DefaultController',
        // ...
    ));
}

Note

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

3.2

The option to add classes to compile using patterns was introduced in Symfony 3.2.

The classes to compile can also be added using file path patterns:

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

    $this->addClassesToCompile(array(
        '**Bundle\\Manager\\',
        // ...
    ));

    $this->addAnnotatedClassesToCompile(array(
        '**Bundle\\Controller\\',
        // ...
    ));
}

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
    We stand with Ukraine.
    Version:
    Online exam, become Symfony certified today

    Online exam, become Symfony certified today

    Code consumes server resources. Blackfire tells you how

    Code consumes server resources. Blackfire tells you how

    Symfony footer

    ↓ Our footer now uses the colors of the Ukrainian flag because Symfony stands with the people of Ukraine.

    Avatar of Bernhard Rusch, a Symfony contributor

    Thanks Bernhard Rusch for being a Symfony contributor

    2 commits • 18 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?

      • Symfony at a Glance
      • Symfony Components
      • Case Studies
      • 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

      • SymfonyConnect
      • Support
      • How to be Involved
      • Code of Conduct
      • Events & Meetups
      • Projects using Symfony
      • Downloads Stats
      • Contributors
      • Backers
    • Blog

      • Events & Meetups
      • A week of symfony
      • Case studies
      • Cloud
      • Community
      • Conferences
      • Diversity
      • Documentation
      • Living on the edge
      • Releases
      • Security Advisories
      • SymfonyInsight
      • Twig
      • SensioLabs
    • Services

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

      Deployed on

    Follow Symfony

    Search by Meilisearch