GotBatteries
GotBatteries

Reputation: 1396

Symfony2 config.yml use expressions with parameters

Is it possible to use parameters in a expression? I have a setting in the parameters.yml, where I define the currently used environment, and I would like to adjust all the configs accordingly. I.e. I have a database connection and I'm trying to set the ip depending on the used env like this(the ip addresses are obviously not the same as the real ones):

doctrine:
    dbal:
        host: "@=%param_current_env% == 'PROD1' ? 0.0.0.0 : 1.1.1.1"

But symfony gives me an error:

Something went wrong. Error: SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: A non-recoverable error occurred during a database lookup.

I'm doing something wrong but what? Is it even possible to use params in the expression, or is the expression itself wrong?

Upvotes: 1

Views: 2587

Answers (1)

Will B.
Will B.

Reputation: 18426

To answer your specific question as of Symfony 2.4 - 3.2; The @= prefix is used to load an Expression object with the string following and can not be dumped by the compiler within the parameters: context. But can be used within the services: context.

See: The bug report on github for more info.


To address your use case; it is best to use environment specific configurations, how Symfony describes in the documentation for creating new environments.

Your directory structure should look something like this.

app
   config
      config.yml
      config_dev.yml
      config_prod.yml
      config_prod1.yml
      config_stage.yml
      ....
      parameters.yml
web
   app.php
   app_dev.php
   app_prod1.php
   app_stage.php

config.yml is meant to contain the configurations, services, and parameters available to all of your environments.

All other config_[environment].yml files can contain environment specific configurations, services, and parameters. Which change the base config.yml values slightly.

parameters.yml contains canonical parameter values, and is by default altered anytime you run php composer.phar install Which should be done anytime you deploy an update to your production environment. So it is best to leave it as maintained by the parameters.yml.dist file and not manually change it.


In order to load a specific environment configuration; Symfony automatically attempts to load the app/config/config_%kernel.environment%.yml files during container compilation by default. So the environment specific configuration loading already exists.

php bin/console --env=prod1 --no-debug cache:warmup

See the AppKernel::registerContainerConfiguration method.

$loader->load($this->getRootDir().'/config/config_'.$this->getEnvironment().'.yml');

However it is up to you to configure your webserver to direct to the desired web front controller file. app.php, app_prod1.php, etc. They tell Symfony which app environment to boot and sets the debug mode.

Copy web/app.php to web/app_prod1.php and change the environment the AppKernel loads.

$kernel = new AppKernel('prod1', false);

Symfony Web Server

php bin/console --env=prod1 server:run  

Apache /web/.htaccess

Change DirectoryIndex on line 1 to the desired environment

DirectoryIndex app_prod1.php

Then change the rewrite rules

RewriteRule .? %{ENV:BASE}/app_prod1.php [L]

and

RedirectMatch 302 ^/$ /app_prod1.php/

Otherwise configure the mod rewrites and disable .htaccess in your VirtualHost file to direct to the desired environment. Which is very subjective to your server environment (php-fpm, NginX, etc).


Once the web server loads the appropriate environment, the configuration files can be cascaded however it is desirable.

config.yml

imports: 
    - { resource: parameters.yml }
    - { resource: security.yml }
    - { resource: services.yml }

framework:
    templating:
        engines: ['twig']
    form: ~

doctrine:
    dbal:
        host: %database_host%
#...

config_prod1.yml

imports:
    - { resource: config.yml } #load the global/default settings

framework:
    form: { enabled: true } #enable the form setting while keeping all other values

#define environment specific services (usually best declared in a bundle)
services:
    app.my_service: '@service'

#override the parameters.yml setting loaded by config.yml or declare new ones
parameters:
    database_host: 192.168.1.2

Alternatives

  1. Separate the config parameters into their individual parameters_%kernel.environment%.yml files and import them individually to their respective environment config files.
  2. Use a Bundle Extension to dynamically configure and load custom parameters.

You can also configure app.php to load different environments based on specific conditions or System Environment Variable. However this does not scale well in production and may cause issues with certain caching mechanisms.

Upvotes: 1

Related Questions