Configuring Symfony (Symfony Docs) (original) (raw)
Configuration Files
Symfony applications are configured with the files stored in the config/directory, which has this default structure:
- The
routes.yamlfile defines the routing configuration; - The
services.yamlfile configures the services of the service container; - The
bundles.phpfile enables/disables packages in your application; - The
config/packages/directory stores the configuration of every package installed in your application.
Packages (also called "bundles" in Symfony and "plugins/modules" in other projects) add ready-to-use features to your projects.
When using Symfony Flex, which is enabled by default in Symfony applications, packages update the bundles.php file and create new files in config/packages/ automatically during their installation. For example, this is the default file created by the "API Platform" bundle:
Splitting the configuration into lots of small files might seem intimidating to some Symfony newcomers. However, you'll get used to them quickly and you rarely need to change these files after package installation.
Configuration Formats
Unlike other frameworks, Symfony doesn't impose a specific format on you to configure your applications, but lets you choose between YAML and PHP. Throughout the Symfony documentation, all configuration examples will be shown in these two formats.
There isn't any practical difference between formats. In fact, Symfony transforms all of them into PHP and caches them before running the application, so there's not even any performance difference.
YAML is used by default when installing packages because it's concise and very readable. These are the main advantages and disadvantages of each format:
- YAML: simple, clean and readable, but not all IDEs support autocompletion and validation for it. Learn the YAML syntax;
- PHP: very powerful and it allows you to create dynamic configuration with arrays, and benefits from auto completion and static analysis using array shapes.
Importing Configuration Files
Symfony loads configuration files using the Config component, which provides advanced features such as importing other configuration files, even if they use a different format:
Configuration Parameters
Sometimes the same configuration value is used in several configuration files. Instead of repeating it, you can define it as a "parameter", which is like a reusable configuration value. By convention, parameters are defined under theparameters key in the config/services.yaml file:
Once defined, you can reference this parameter value from any other configuration file using a special syntax: wrap the parameter name in two %(e.g. %app.admin_email%):
Note
If some parameter value includes the % character, you need to escape it by adding another %, so Symfony doesn't consider it a reference to a parameter name:
Note
Due to the way in which parameters are resolved, you cannot use them to build paths in imports dynamically. This means that something likethe following does not work:
Configuration parameters are very common in Symfony applications. Some packages even define their own parameters (e.g. when installing the translation package, a new locale parameter is added to the config/services.yaml file).
Tip
By convention, parameters whose names start with a dot . (for example,.mailer.transport), are available only during the container compilation. They are useful when working with Compiler Passesto declare some temporary parameters that won't be available later in the application.
Configuration parameters are usually validation-free, but you can ensure that essential parameters for your application's functionality are not empty:
If a non-empty parameter is null, an empty string '', or an empty array [], Symfony will throw an exception. This validation is not made at compile time but when attempting to retrieve the value of the parameter.
Configuration Environments
You have only one application, but whether you realize it or not, you need it to behave differently at different times:
- While developing, you want to log everything and expose nice debugging tools;
- After deploying to production, you want that same application to be optimized for speed and only log errors.
The files stored in config/packages/ are used by Symfony to configure theapplication services. In other words, you can change the application behavior by changing which configuration files are loaded. That's the idea of Symfony's configuration environments.
A typical Symfony application begins with three environments:
devfor local development,prodfor production servers,testfor automated tests.
When running the application, Symfony loads the configuration files in this order (the last files can override the values set in the previous ones):
- The files in
config/packages/*.<extension>; - the files in
config/packages/<environment-name>/*.<extension>; config/services.<extension>;config/services_<environment-name>.<extension>.
Take the framework package, installed by default, as an example:
- First,
config/packages/framework.yamlis loaded in all environments and it configures the framework with some options; - In the prod environment, nothing extra will be set as there is no
config/packages/prod/framework.yamlfile; - In the dev environment, there is no file either (
config/packages/dev/framework.yamldoes not exist). - In the test environment, the
config/packages/test/framework.yamlfile is loaded to override some of the settings previously configured inconfig/packages/framework.yaml.
In reality, each environment differs only somewhat from others. This means that all environments share a large base of common configuration, which is put in files directly in the config/packages/ directory.
Tip
You can also define options for different environments in a single configuration file using the special when keyword:
See also
See the configureContainer() method ofthe Kernel class to learn everything about the loading order of configuration files.
Selecting the Active Environment
Symfony applications come with a file called .env located at the project root directory. This file is used to define the value of environment variables and it's explained in detail later in this article.
Open the .env file (or better, the .env.local file if you created one) and edit the value of the APP_ENV variable to change the environment in which the application runs. For example, to run the application in production:
This value is used both for the web and for the console commands. However, you can override it for commands by setting the APP_ENV value before running them:
Creating a New Environment
The default three environments provided by Symfony are enough for most projects, but you can define your own environments too. For example, this is how you can define a staging environment where the client can test the project before going to production:
- Create a configuration directory with the same name as the environment (in this case,
config/packages/staging/); - Add the needed configuration files in
config/packages/staging/to define the behavior of the new environment. Symfony loads theconfig/packages/*.yamlfiles first, so you only need to configure the differences to those files; - Select the
stagingenvironment using theAPP_ENVenv var as explained in the previous section.
Tip
It's common for environments to be similar to each other, so you can use symbolic links between config/packages/<environment-name>/directories to reuse the same configuration.
Instead of creating new environments, you can use environment variables as explained in the following section. This way you can use the same application and environment (e.g. prod) but change its behavior thanks to the configuration based on environment variables (e.g. to run the application in different scenarios: staging, quality assurance, client review, etc.)
Configuration Based on Environment Variables
Using environment variables (or "env vars" for short) is a common practice to:
- Configure options that depend on where the application is run (e.g. the database credentials are usually different in production versus your local machine);
- Configure options that can change dynamically in a production environment (e.g. to update the value of an expired API key without having to redeploy the entire application).
In other cases, it's recommended to keep using configuration parameters.
Use the special syntax %env(ENV_VAR_NAME)% to reference environment variables. The values of these options are resolved at runtime (only once per request, to not impact performance) so you can change the application behavior without having to clear the cache.
This example shows how you could configure the application secret using an env var:
Note
Your env vars can also be accessed via the PHP super globals $_ENV and$_SERVER (both are equivalent):
However, in Symfony applications there's no need to use this, because the configuration system provides a better way of working with env vars.
See also
The values of env vars can only be strings, but Symfony includes someenv var processors to transform their contents (e.g. to turn a string value into an integer).
To define the value of an env var, you have several options:
- Add the value to a .env file;
- Encrypt the value as a secret;
- Set the value as a real environment variable in your shell or your web server.
If your application tries to use an env var that hasn't been defined, you'll see an exception. You can prevent that by defining a default value for the env var. To do so, define a parameter with the same name as the env var using this syntax:
Note
Some configuration features are not compatible with env vars. For example, defining some container parameters conditionally based on the existence of another configuration option. When using an env var, the configuration option always exists, because its value will be null when the related env var is not defined.
Danger
Beware that dumping the contents of the $_SERVER and $_ENV variables or outputting the phpinfo() contents will display the values of the environment variables, exposing sensitive information such as the database credentials.
The values of the env vars are also exposed in the web interface of theSymfony profiler. In practice this shouldn't be a problem because the web profiler must never be enabled in production.
Configuring Environment Variables in .env Files
Instead of defining env vars in your shell or your web server, Symfony provides a convenient way to define them inside a .env (with a leading dot) file located at the root of your project.
The .env file is read and parsed on every request and its env vars are added to the $_ENV & $_SERVER PHP variables. Any existing env vars are _never_overwritten by the values defined in .env, so you can combine both.
For example, to define the DATABASE_URL env var shown earlier in this article, you can add:
This file should be committed to your repository and (due to that fact) should only contain "default" values that are good for local development. This file should not contain production values.
In addition to your own env vars, this .env file also contains the env vars defined by the third-party packages installed in your application (they are added automatically by Symfony Flex when installing packages).
Tip
Since the .env file is read and parsed on every request, you don't need to clear the Symfony cache or restart the PHP container if you're using Docker.
.env File Syntax
Add comments by prefixing them with #:
Use environment variables in values by prefixing variables with $:
Warning
The order is important when some env var depends on the value of other env vars. In the above example, DB_PASS must be defined after DB_USER. Moreover, if you define multiple .env files and put DB_PASS first, its value will depend on the DB_USER value defined in other files instead of the value defined in this file.
Define a default value in case the environment variable is not set:
Embed commands via $() (not supported on Windows):
Warning
Using $() might not work depending on your shell.
Tip
As a .env file is a regular shell script, you can source it in your own shell scripts:
Overriding Environment Values via .env.local
If you need to override an environment value (e.g. to a different value on your local machine), you can do that in a .env.local file:
This file should be ignored by git and should not be committed to your repository. Several other .env files are available to set environment variables in _just_the right situation:
.env: defines the default values of the env vars needed by the application;.env.local: overrides the default values for all environments but only on the machine which contains the file. This file should not be committed to the repository and it's ignored in thetestenvironment (because tests should produce the same results for everyone);.env.<environment>(e.g..env.test): overrides env vars only for one environment but for all machines (these files are committed);.env.<environment>.local(e.g..env.test.local): defines machine-specific env var overrides only for one environment. It's similar to.env.local, but the overrides only apply to one environment.
Real environment variables always win over env vars created by any of the.env files. Note that this behavior depends on thevariables_orderconfiguration, which must contain an E to expose the $_ENV superglobal. This is the default configuration in PHP.
The .env and .env.<environment> files should be committed to the repository because they are the same for all developers and machines. However, the env files ending in .local (.env.local and .env.<environment>.local)should not be committed because only you will use them. In fact, the.gitignore file that comes with Symfony prevents them from being committed.
Overriding Environment Variables Defined By The System
If you need to override an environment variable defined by the system, use theoverrideExistingVars parameter defined by theloadEnv(),bootEnv(), andpopulate() methods:
This will override environment variables defined by the system but it won'toverride environment variables defined in .env files.
Configuring Environment Variables in Production
In production, the .env files are also parsed and loaded on each request. So the easiest way to define env vars is by creating a .env.local file on your production server(s) with your production values.
To improve performance, you can optionally run the dump-env Composer command:
After running this command, Symfony will load the .env.local.php file to get the environment variables and will not spend time parsing the .env files.
Tip
Update your deployment tools/workflow to run the dotenv:dump command after each deploy to improve the application performance.
Storing Environment Variables In Other Files
By default, the environment variables are stored in the .env file located at the root of your project. However, you can store them in other files in multiple ways.
If you use the Runtime component, the dotenv path is part of the options you can set in your composer.json file:
As an alternate option, you can directly invoke the Dotenv class in yourbootstrap.php file or any other file of your application:
Symfony will then look for the environment variables in that file, but also in the local and environment-specific files (e.g. .*.local and.*.<environment>.local). Readhow to override environment variablesto learn more about this.
If you need to know the path to the .env file that Symfony is using, you can read the SYMFONY_DOTENV_PATH environment variable in your application.
Encrypting Environment Variables (Secrets)
Instead of defining a real environment variable or adding it to a .env file, if the value of a variable is sensitive (e.g. an API key or a database password), you can encrypt the value using the secrets management system.
Listing Environment Variables
Use the debug:dotenv command to understand how Symfony parses the different.env files to set the value of each environment variable:
Additionally, and regardless of how you set environment variables, you can see all environment variables, with their values, referenced in Symfony's container configuration, you can also see the number of occurrences of each environment variable in the container:
Creating Your Own Logic To Load Env Vars
You can implement your own logic to load environment variables if the default Symfony behavior doesn't fit your needs. To do so, create a service whose class implements EnvVarLoaderInterface.
Let's say you have a JSON file named env.json containing your environment variables:
You can define a class like the following JsonEnvVarLoader to populate the environment variables from the file:
That's it! Now the application will look for a env.json file in the current directory to populate environment variables (in addition to the already existing .env files).
Tip
If you want an env var to have a value on a certain environment but to fallback on loaders on another environment, assign an empty value to the env var for the environment you want to use loaders:
Accessing Configuration Parameters
Controllers and services can access all the configuration parameters. This includes both the parameters defined by yourselfand the parameters created by packages/bundles. Run the following command to see all the parameters that exist in your application:
In controllers extending from the AbstractController, use the getParameter() helper:
In services and controllers not extending from AbstractController, inject the parameters as arguments of their constructors. You must inject them explicitly because service autowiringdoesn't work for parameters:
If you inject the same parameters over and over again, use theservices._defaults.bind option instead. The arguments defined in that option are injected automatically whenever a service constructor or controller action defines an argument with that exact name. For example, to inject the value of thekernel.project_dir parameterwhenever a service/controller defines a $projectDir argument, use this:
Finally, if some service needs access to lots of parameters, instead of injecting each of them individually, you can inject all the application parameters at once by type-hinting any of its constructor arguments with theContainerBagInterface:
This work, including the code samples, is licensed under aCreative Commons BY-SA 3.0 license.