Skip to content

[DependencyInjection] Document %env(...)% dynamic parameters #6918

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 14, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 81 additions & 86 deletions configuration/external_parameters.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,119 +13,114 @@ you to easily do this.
Environment Variables
---------------------

Symfony will grab any environment variable prefixed with ``SYMFONY__`` and
set it as a parameter in the service container. Some transformations are
applied to the resulting parameter name:

* ``SYMFONY__`` prefix is removed;
* Parameter name is lowercased;
* Double underscores are replaced with a period, as a period is not
a valid character in an environment variable name.

For example, if you're using Apache, environment variables can be set using the
`SetEnv`_ directive with the following ``VirtualHost`` configuration:

.. code-block:: apache

<VirtualHost *:80>
ServerName Symfony
DocumentRoot "/path/to/symfony_2_app/web"
DirectoryIndex index.php index.html
SetEnv SYMFONY__DATABASE__USER user
SetEnv SYMFONY__DATABASE__PASSWORD secret

<Directory "/path/to/symfony_2_app/web">
AllowOverride All
Allow from All
</Directory>
</VirtualHost>

For Nginx web servers, the environment variables can be set with the `fastcgi_param`_
directive. For example, in the configuration file where the ``fastcgi_params``
file is included:

.. code-block:: nginx

server {
server_name domain.tld www.domain.tld;
root /var/www/project/web;

location / {
try_files $uri /app.php$is_args$args;
}

location ~ ^/app\.php(/|$) {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
fastcgi_param SYMFONY__DATABASE__USER user;
fastcgi_param SYMFONY__DATABASE__PASSWORD secret;
internal;
}

# ...
}
.. versionadded:: 3.2
``env()`` parameters were introduced in Symfony 3.2.

.. note::

The examples above are for an Apache and Nginx configuration. However, this
will work for any web server which supports the setting of environment
variables.

Also, in order for your console to work (which does not use a web server),
you must export these as shell variables. On a Unix system, you can run
the following:

.. code-block:: terminal
You can reference environment variables by using special parameters named after
the variables you want to use enclosed between ``env()``. Their actual values
will be resolved at runtime (once per request), so that dumped containers can be
reconfigured dynamically even after being compiled.

$ export SYMFONY__DATABASE__USER=user
$ export SYMFONY__DATABASE__PASSWORD=secret

Now that you have declared an environment variable, it will be present
in the PHP ``$_SERVER`` global variable. Symfony then automatically sets all
``$_SERVER`` variables prefixed with ``SYMFONY__`` as parameters in the service
container.

You can now reference these parameters wherever you need them.
For example, if you want to use the value of the ``DATABASE_HOST`` environment
variable in you service container configuration, you can reference it using
``%env(DATABASE_HOST)%`` in your configuration files:

.. configuration-block::

.. code-block:: yaml

# app/config/config.yml
doctrine:
dbal:
driver: pdo_mysql
dbname: symfony_project
user: '%database.user%'
password: '%database.password%'
host: '%env(DATABASE_HOST)%'

.. code-block:: xml

<!-- app/config/config.xml -->
<!-- xmlns:doctrine="http://symfony.com/schema/dic/doctrine" -->
<!-- xsi:schemaLocation="http://symfony.com/schema/dic/doctrine http://symfony.com/schema/dic/doctrine/doctrine-1.0.xsd"> -->

<doctrine:config>
<doctrine:dbal
driver="pdo_mysql"
dbname="symfony_project"
user="%database.user%"
password="%database.password%"
host="%env(DATABASE_HOST)%"
/>
</doctrine:config>

.. code-block:: php

// app/config/config.php
$container->loadFromExtension('doctrine', array(
'dbal' => array(
'driver' => 'pdo_mysql',
'dbname' => 'symfony_project',
'user' => '%database.user%',
'password' => '%database.password%',
'host' => '%env(DATABASE_HOST)%',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One can wonder "why not using getenv directly". I know why, but I could be nice to explain why ?!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, at least I don't know how to phrase it :) This is explained indirectly a few lines below this one. If someone has any suggestions, please do, otherwise I might leave it asis.

Copy link
Member

@wouterj wouterj Aug 25, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I propose the following:

  • Keep the "Environment variables" section title and document the %env(...)% syntax in there. Explain what by reference means ("You can reference environment variables using the %env(...)% syntax. The actual value will be resolved when using the container: [...]").
  • Add a small .. note:: directive documenting SYMFONY__ (I personally don't see any reason to use this, other than BC. In other words, why not deprecate it?). This will say something like: "You can also directly set parameters by prefixing the environment variable with SYFMONY__ (e.g. SYMFONY__DATABASE__USER would set a database.user parameter). This value will be resolved when warming up the cache and will not change at runtime."

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wouterj PR updated accordingly

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wouterj I agree with your deprecation proposal. I've created symfony/symfony#20089 for that.

)
));

You can also give the ``env()`` parameters a default value: the default value
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... a default value: the default value will be used whenever ...

-->

... a default value used whenever ...

will be used whenever the corresponding environment variable is *not* found:

.. configuration-block::

.. code-block:: yaml

# app/config/parameters.yml
parameters:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add #app/config/parameters.yml above this - it's probably the file where they will define the default value

database_host: '%env(DATABASE_HOST)%'
env(DATABASE_HOST): localhost
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this functionality part of the symfony/symfony#19681 PR? I've tried something similar with:

database_driver: 'env(DATABASE_DRIVER): pdo_mysql'

but it doesn't use the default and just complains that:

"The given 'driver' env(DATABASE_DRIVER): pdo_mysql is unknown"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mickadoo your code is not what is documented here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stof I just thought I'd try it out, didn't work though

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's documented here is:

parameters:
    database_driver: '%env(DATABASE_DRIVER)%'
    env(DATABASE_DRIVER): pdo_mysql

Which, as you can see, is quite different from the format you tested. If there is something we can do to improve the description of the feature, please tell us!

Copy link
Contributor

@mickadoo mickadoo Oct 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wouterj Ah, I get it now. Sorry about that!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem @mickadoo thanks for test-casing this documentation proposal.

I think we should include the database_driver: '%env(DATABASE_DRIVER)%' line in this example to avoid confusing for other readers.


.. code-block:: xml

<!-- app/config/parameters.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing filename comment

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for the PHP config example

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have an example of such filenames for xml & php?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually simply replace the file extension. So here we would have app/config/parameters.yml, app/config/parameters.xml, and app/config/parameters.php. By the way, can you also add similar comments in the example above to, but using config.yml, config.xml, and config.php there?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah well, the previous example is not new. We should add the comments there in older branches too and can probably better do that in a separate PR.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it, fixed

<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<parameters>
<parameter key="database_host">%env(DATABASE_HOST)%</parameter>
<parameter key="env(DATABASE_HOST)">localhost</parameter>
</parameters>
</container>

.. code-block:: php

// app/config/parameters.php
$container->setParameter('database_host', '%env(DATABASE_HOST)%');
$container->setParameter('env(DATABASE_HOST)', 'localhost');

Setting environment variables is generally done at the web server level or in the
terminal. If you're using Apache, Nginx or just the console, you can use e.g. one
of the following:

.. configuration-block::

.. code-block:: apache
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking at the tests, apache here makes sphinx fail, any clue why?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apache has no label configured. Please edit the _build/conf.py file and add: 'apache': 'Apache' (same for the other formats in this block). (and also ping javier that the symfony.com config has to be updated)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wouterj thanks for the heads up. It will be merged in symfony.com soon:

apache-sphinx

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@javiereguiluz please note that you also have to add 'nginx': 'NGINX'

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wouterj thanks! It's fixed now. I opted for Nginx as the human-readable name instead of NGINX. The official website mixes nginx, Nginx and NGINX ... but the Wikipedia always uses Nginx.


<VirtualHost *:80>
# ...

SetEnv DATABASE_USER user
SetEnv DATABASE_PASSWORD secret
</VirtualHost>

.. code-block:: nginx

fastcgi_param DATABASE_USER user
fastcgi_param DATABASE_PASSWORD secret

.. code-block:: terminal

$ export DATABASE_USER=user
$ export DATABASE_PASSWORD=secret

.. tip::

You can also define the default value of any existing parameters using
special environment variables named after their corresponding parameter
prefixed with ``SYMFONY__`` after replacing dots by double underscores
(e.g. ``SYMFONY__KERNEL__CHARSET`` to set the default value of the
``kernel.charset`` parameter). These default values are resolved when
compiling the service container and won't change at runtime once dumped.

Constants
---------

Expand Down