In Symfony 2 there are two main ways to define configuration options for a bundle. The first way is to simply define parameters in the service container and the second is to expose semantic configuration for your bundle. Whether to use parameters or expose semantic configuration should be determined by the type of configuration needed and whether the bundle will be reused and/or distributed. Semantic configuration offers many benefits over simply using parameters, but is slightly more involved to implement.

 

Using Parameters

Using parameters in your application allows you to keep simple configuration, account details, api keys, email addresses, and magic numbers in a single place. The benefits of using parameters are that they decouple your configuration and constants from your code. They also allow you to use separate sets of parameters for different environments. Symfony has excellent documentation on how to use parameters. There are some drawbacks to using parameters though. Users of the bundle need to know they exist and how to use them. There is no enforcement or validation, and parameters can’t be logically nested. Parameters are limited to configuration constants, and if an entire portion of the bundle may change based on configuration then a parameter may not be a good choice.

 

Exposing Semantic Configuration

A great alternative to relying solely on parameters is to expose semantic configuration for your bundle. This allows users of the bundle to specify configuration options in the main configuration file. Some of the benefits of using configuration vs. parameters are below.

– Using configuration can allow you to completely change the way services are defined and what services are available by loading service files differently based on configuration values.

– Configuration options can also use default values, enforce required settings, be validated, and restrict values to a list of available options.

– Configuration can also be nested to allow for a tree of settings and to logically group settings.

– Configuration can also be self documenting, allowing users of the bundle to easily determine default settings and available options.

– Configuration also decouples the parameters from the services that use them, which are often included in the same file within a bundle. It allows configuration options to remain with the app and parameters to be portable with the bundle.

There is a higher level of effort required to use configuration as opposed to parameters and the process is a slightly more complex.

 

Defining Configuration

Configuration Class

The configuration class, located in a bundles DependencyInjection directory, allows a bundle to expose semantic configuration. This allows users to set bundle options by adding to Symfony’s main configuration files, ie. app/config/config.yml. By adding configuration using the TreeBuilder, you can expose different configuration options, default values, allowed options, and validation rules to create a configuration tree. Symfony has excellent documentation on how to define and process configuration values so I won’t go into complete detail beyond a simple example of defining a bundle configuration.

The tree builder starts with a root node, which is created by default when using the app_console generate:bundle command. Setting the children of the root node will add configuration options nested beneath it in the configuration tree. Possible child node types are scalar, boolean, integer, float, enum, array, and variable. It is possible to set deafult or required values using the defaultValue() method. More advanced validation can also be added, such as testing if a value is a string or in an array.

This example shows defining a few different configuration settings, including child configuration, basic validation, and default values.

 

Setting Configuration Options

This is how you would configure these options in app/config/config.yml file.

 

Documenting the Configuration

After creating this configuration, full configuration definition documentation can be viewed using the app/console config:dump-reference terminal command. This will show the default bundle configuration in yml, including whether nodes are required to be set. The configuration above looks like this.

 

Dependency Injection Extension Class

The dependency injection extension class allows your bundle to load service configuration, and this is where you can access the configuration options that are set in the main config file, ie. app/config/config.yml. This is where you can take action based on the configuration options. For instance, you can convert the configuration into different parameters that can then be injected into services or you can conditionally load additional configuration files based on the configuration values.

Below, the load() method is merging the configuration, accessing that configuration and setting parameters that can later be used by other services.

 

Another option is to conditionally load an additional configuration file that contains more service and parameter definitions. This file could override some default services or redefine a number of parameters, depending on what you need to do. This example shows how to load an optional services file based on the value of a configuration option.

 

Supporting XML

There are some additonal steps that need to be taken to support the use of XML configuration files. You’ll need to define a namespace and create an XML schema. More information on that can be found here.

 

Conclusion

If your bundle does not rely heavily on parameters and will not be reused then a simple parameter may be all you need. Exposing semantic configuration in Symfony is a little more involved than simply using parameters, but if you intend to share or reuse your bundle on multiple projects then it is well worth the additional effort.