Дата оновлення перекладу 2022-05-10

Як встановлювати зовнішні параметри в сервіс-контейнері

В Configuring Symfony ви дізналися, як управляти конфігурацією вашого додатку. В деяких випадках вашому додатку може піти на користь зберігання деяких сертифікатів поза кодом вашого проекту. Конфігурація бази даних є одним з таких прикладів. Гнучкість сервіс-контейнера Symfony дозволяє вам з легкістю робити це.

Змінні середовища

Ви можете посилатися на зміння середовища, використовуючи спеціальні параметри, які названі на честь тих змінних, які ви хочете використовувати, оточені env(). Їх справжні значення будуть дозволені під час прогону (один раз на запит), щоб скинути контейнери могли бути знов динамічно сконфігуровані навіть після компіляції.

Наприклад, при встановленні рецепту doctrine, конфігурація DB розміщується у змінній середовища DATABASE_URL:

1
2
# .env
DATABASE_URL="mysql://db_user:[email protected]:3306/db_name"

На цю змінну посилаються в конфігурації сервіс-контейнера, використовуючи %env(DATABASE_URL)%:

  • YAML
    1
    2
    3
    4
    5
    # config/packages/doctrine.yaml
    doctrine:
        dbal:
            url: '%env(DATABASE_URL)%'
        # ...
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    <!-- config/packages/doctrine.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:doctrine="http://symfony.com/schema/dic/doctrine"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/doctrine
            http://symfony.com/schema/dic/doctrine/doctrine-1.0.xsd">
    
        <doctrine:config>
            <doctrine:dbal
                url="%env(DATABASE_URL)%"
            />
        </doctrine:config>
    
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    // config/packages/doctrine.php
    $container->loadFromExtension('doctrine', array(
        'dbal' => array(
            'url' => '%env(DATABASE_URL)%',
        )
    ));
    

Ви також можете давати параметрам env() значення за замовчуванням: значення за замовчуванням буде використане кожен раз, коли не знайдено відповідну змінну середовища:

  • YAML
    1
    2
    3
    # config/services.yaml
    parameters:
        env(DATABASE_HOST): localhost
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    <!-- config/services.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <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="env(DATABASE_HOST)">localhost</parameter>
        </parameters>
     </container>
    
  • PHP
    1
    2
    // config/services.php
    $container->setParameter('env(DATABASE_HOST)', 'localhost');
    

Конфігурація змінних середовища у виробництві

Під час розробки ви використовуватимете файл .env, щоб сконфігурувати ваші змінні середовища. На вашому сервері виробництва рекомендовано конфігурувати змінні на рівні веб-серверу. Якщо ви використовуєте Apache або Nginx, то ви можете використовувати, наприклад, наступне:

  • Apache
    1
    2
    3
    4
    5
    <VirtualHost *:80>
        # ...
    
        SetEnv DATABASE_URL "mysql://db_user:[email protected]:3306/db_name"
    </VirtualHost>
    
  • Nginx
    1
    fastcgi_param DATABASE_URL "mysql://db_user:[email protected]:3306/db_name";
    

Caution

Майте на увазі, що скидання змісту змінних $_SERVER та $_ENV або виведення змісту phpinfo() відобразить значення змінних середовища, оголюючи чутливу інформацію, на кшталт сертифікатів бази даних.

Значення змінних середовища також відображаються у веб-інтерфейсі Symfony профільувальника. На практиці це не повинно бути проблемаою, тому що веб-профільувальник ніколи не має бути увімкнений у виробництві.

Процесори змінних середовища

New in version 3.4: Процесори змінних середовища з’явилися в Symfony 3.4.

Значення змінних середовища за замовчуванням вважаються рядками. Однак ваш код може очікувати інші типи даних, наприклад, цілі числа або булеві значення. Symfony вирішує цю проблему процесорами, які перетворюють зміст вказаних змінних середовища. Наступний приклад використовує процесор цілих чисел для перетворення значення змінної середовища HTTP_PORT в ціле число:

  • YAML
    1
    2
    3
    4
    # config/packages/framework.yaml
    framework:
        router:
            http_port: env(int:HTTP_PORT)
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    <!-- config/packages/framework.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <framework:config>
            <framework:router http-port="%env(int:HTTP_PORT)%" />
        </framework:config>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    // config/packages/framework.php
    $container->loadFromExtension('framework', array(
        'router' => array(
            'http_port' => '%env(int:HTTP_PORT)%',
        ),
    ));
    

Symfony надає наступні процесори змінних середовища:

env(string:FOO)

Перетворює FOO в рядок:

  • YAML
    1
    2
    3
    4
    5
    # config/packages/framework.yaml
    parameters:
        env(SECRET): 'some_secret'
    framework:
       secret: '%env(string:SECRET)%'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    <!-- config/packages/framework.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <parameters>
            <parameter key="env(SECRET)">some_secret</parameter>
        </parameters>
    
        <framework:config secret="%env(string:SECRET)%" />
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    // config/packages/framework.php
    $container->setParameter('env(SECRET)', 'some_secret');
    $container->loadFromExtension('framework', array(
        'secret' => '%env(string:SECRET)%',
    ));
    
env(bool:FOO)

Перетворює FOO в булеве значення:

  • YAML
    1
    2
    3
    4
    5
    # config/packages/framework.yaml
    parameters:
        env(HTTP_METHOD_OVERRIDE): 'true'
    framework:
       http_method_override: '%env(bool:HTTP_METHOD_OVERRIDE)%'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    <!-- config/packages/framework.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <parameters>
            <parameter key="env(HTTP_METHOD_OVERRIDE)">true</parameter>
        </parameters>
    
        <framework:config http-methode-override="%env(bool:HTTP_METHOD_OVERRIDE)%" />
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    // config/packages/framework.php
    $container->setParameter('env(HTTP_METHOD_OVERRIDE)', 'true');
    $container->loadFromExtension('framework', array(
        'http_method_override' => '%env(bool:HTTP_METHOD_OVERRIDE)%',
    ));
    
env(int:FOO)
Перетворює FOO в значення цілого числа.
env(float:FOO)
Перетворює FOO в дробове число.
env(const:FOO)

Знаходить значення константи, визначеної в FOO:

  • YAML
    1
    2
    3
    4
    5
    6
    # config/packages/security.yaml
    parameters:
        env(HEALTH_CHECK_METHOD): 'Symfony\Component\HttpFoundation\Request::METHOD_HEAD'
    security:
       access_control:
         - { path: '^/health-check$', methods: '%env(const:HEALTH_CHECK_METHOD)%' }
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    <!-- config/packages/security.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:security="http://symfony.com/schema/dic/security"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <parameters>
            <parameter key="env(HEALTH_CHECK_METHOD)">Symfony\Component\HttpFoundation\Request::METHOD_HEAD</parameter>
        </parameters>
    
        <security:config>
            <rule path="^/health-check$" methods="%env(const:HEALTH_CHECK_METHOD)%" />
        </security:config>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    // config/packages/security.php
    $container->setParameter('env(HEALTH_CHECK_METHOD)', 'Symfony\Component\HttpFoundation\Request::METHOD_HEAD');
    $container->loadFromExtension('security', array(
        'access_control' => array(
            array(
                'path' => '^/health-check$',
                'methods' => '%env(const:HEALTH_CHECK_METHOD)%',
            ),
        ),
    ));
    
env(base64:FOO)
Декодує зміст FOO, яке є закодованим base64 рядком.
env(json:FOO)

Декодує зміст FOO, яке є закодованим JSON рядком. Повертає масив або null:

  • YAML
    1
    2
    3
    4
    5
    # config/packages/framework.yaml
    parameters:
        env(TRUSTED_HOSTS): '["10.0.0.1", "10.0.0.2"]'
    framework:
       trusted_hosts: '%env(json:TRUSTED_HOSTS)%'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    <!-- config/packages/framework.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <parameters>
            <parameter key="env(TRUSTED_HOSTS)">["10.0.0.1", "10.0.0.2"]</parameter>
        </parameters>
    
        <framework:config trusted-hosts="%env(json:TRUSTED_HOSTS)%" />
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    // config/packages/framework.php
    $container->setParameter('env(TRUSTED_HOSTS)', '["10.0.0.1", "10.0.0.2"]');
    $container->loadFromExtension('framework', array(
        'trusted_hosts' => '%env(json:TRUSTED_HOSTS)%',
    ));
    
env(resolve:FOO)

Замінює рядок FOO значенням конфігураційного параметру з цим значенням:

  • YAML
    1
    2
    3
    4
    5
    6
    # config/packages/sentry.yaml
    parameters:
        env(HOST): '10.0.0.1'
        env(SENTRY_DSN): 'http://%env(HOST)%/project'
    sentry:
        dsn: '%env(resolve:SENTRY_DSN)%'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    <!-- config/packages/sentry.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <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="env(HOST)">10.0.0.1</parameter>
            <parameter key="env(SENTRY_DSN)">http://%env(HOST)%/project</parameter>
        </parameters>
    
        <sentry:config dsn="%env(resolve:SENTRY_DSN)%" />
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    // config/packages/sentry.php
    $container->setParameter('env(HOST)', '10.0.0.1');
    $container->setParameter('env(SENTRY_DSN)', 'http://%env(HOST)%/project');
    $container->loadFromExtension('sentry', array(
        'dsn' => '%env(resolve:SENTRY_DSN)%',
    ));
    
env(csv:FOO)

Декодує зміст FOO, яке є закодованим CSV рядком:

1
2
3
4
parameters:
    env(TRUSTED_HOSTS): "10.0.0.1, 10.0.0.2"
framework:
   trusted_hosts: '%env(csv:TRUSTED_HOSTS)%'

New in version 4.1: Процесор csv з’явився в Symfony 4.1.

env(file:FOO)

Повертає зміст файлу, шлях до якого вказано у змінній середовища FOO:

  • YAML
    1
    2
    3
    4
    5
    # config/packages/framework.yaml
    parameters:
        env(AUTH_FILE): '../config/auth.json'
    google:
        auth: '%env(file:AUTH_FILE)%'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    <!-- config/packages/framework.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <parameters>
            <parameter key="env(AUTH_FILE)">../config/auth.json</parameter>
        </parameters>
    
        <google auth="%env(file:AUTH_FILE)%" />
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    // config/packages/framework.php
    $container->setParameter('env(AUTH_FILE)', '../config/auth.json');
    $container->loadFromExtension('google', array(
        'auth' => '%env(file:AUTH_FILE)%',
    ));
    

Можна також комбінувати будь-яку кількість процесорів:

1
2
3
4
5
6
7
8
parameters:
    env(AUTH_FILE): "%kernel.project_dir%/config/auth.json"
google:
    # 1. отримує значення змінної середовища AUTH_FILE
    # 2. замінює значення конфігураційним параметром для отримання шляху до конфігурації
    # 3. отримує зміст файлу, збереженого за цим шляхом
    # 4. JSON-декодує зміст файлу та повертає його
    auth: '%env(json:file:resolve:AUTH_FILE)%'

Користувацькі процесори змінних середовища

Також можливо додавати власні процесори для користувацьких змінних. Спочатку створіть клас, який реалізує EnvVarProcessorInterface, а потім визначте сервіс для цього класу:

class LowercasingEnvVarProcessor implements EnvVarProcessorInterface
{
    private $container;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    public function getEnv($prefix, $name, \Closure $getEnv)
    {
        $env = $getEnv($name);

        return strtolower($env);
    }

    public static function getProvidedTypes()
    {
        return [
            'lowercase' => 'string',
        ];
    }
}

Константи

Контейнер також має підтримку для установки PHP-констант в якості параметрів. Див. component-di-parameters-constants, щоб дізнатися більш детально.

Змішана конфігурація

Ви можете змішувати будь-які формати конфігурації на свій смак (YAML, XML та PHP) в config/packages/. Імпорт PHP-файлу дає вам можливість додавати все, що потрібно, в контейнер. Наприклад, ви можете створити файл drupal.php, в якому ви встановите URL бази даних, заснований на конфігурації DB Drupal:

// config/packages/drupal.php

// імпортувати конфігурацію Drupal
include_once('/path/to/drupal/sites/default/settings.php');

// встановити параметр app.database_url
$container->setParameter('app.database_url', $db_url);

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.