Дата обновления перевода: 2021-05-13

Конфигурация Symfony

Файлы конфигурации

Приложения Symfony сконфигурированы с файлами, хранящимися в каталоге config/, который по умолчанию имеет следующую структуру:

1
2
3
4
5
6
7
your-project/
├─ config/
│  ├─ packages/
│  ├─ bundles.php
│  ├─ routes.yaml
│  └─ services.yaml
├─ ...

Файл routes.yaml определяет конфигурацию маршрутизации; файл services.yaml конфигурирует сервисы сервис-контейнера; файл bundles.php включает/ выключает пакеты в вашем приложении.

Вы будете в основном работать в каталоге config/packages/. Этот каталог сохраняет конфигурацию каждого пакета, установленного в вашем приложении. Пакеты (которые также называются “плагины/модули” в других проектах) добавляют готовые к использованию функции в ваши проекты.

При использовании Symfony Flex, который в приложениях Symfony включен по умолчанию, пакеты обновляют файл bundles.php и создают новые файлы в config/packages/ автоматически во время установки. К примеру, это файл по умолчанию, созданный пакетом “API Platform”:

1
2
3
4
# config/packages/api_platform.yaml
api_platform:
    mapping:
        paths: ['%kernel.project_dir%/src/Entity']

Разделение конфигурации на множество маленьких файлов пугает некоторых новичков в Symfony. Однако, вы быстро к ним привыкнете и вам редко когда нужно будет менять эти файлы после утсановки пакета.

Tip

Чтобы узнать все о доступных опциях конфигурации, посмотрите справочник конфигурации Symfony или выполните команду config:dump-reference.

Форматы конфигурации

В отличие от других фреймворков, Symfony не заставляет вас использовать конкретный формат для конфигурации приложения. Symfony позволяет вам выбирать между YAML, XML и PHP, и по всей документации Symfony, все примеры конфигурации будут показаны в этих трех форматах.

Между форматами нет практической разницы. На самом деле, Symfony транформирует и кэширует их все в PHP перед запуском приложения, так что между ними даже нет разницы в производиельности.

YAML используется по умолчанию при установке пакетов так как он лаконичный и очень читаемый. Вот основные преимущества и недостатки каждого формата:

  • YAML: простой, чистый и читаемый, но не все IDE поддерживают автозаполнение и валидацию для него. Узнайте о синтаксисе YAML;
  • XML: автозаполняется/валидируется большинством IDE и нативно анализируется PHP, но иногда генерирует конфигурацию, которая считается слишком перегруженным. `Изучите синтаксис XML`_;
  • PHP: очень мощний и позволяет вам создавать динамическую конфигурацию с массивами или ConfigBuilder.

Импортирование файлов конфигурации

Symfony загружает файлы конфигурации используя компонент Config, который предоставляет продвинутые функции, такие как импорт других файлов конфигурации, даже если они используют другой формат:

  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    # config/services.yaml
    imports:
        - { resource: 'legacy_config.php' }
    
        # глобальные выражения также поддерживают загрузку нескольких файлов
        - { resource: '/etc/myapp/*.yaml' }
    
        # ignore_errors: not_found тихо удаляет ошибки в случае если загруженный файл не существует
        - { resource: 'my_config_file.xml', ignore_errors: not_found }
        # ignore_errors: true тихо удаляет все ошибки (включая неверный код и не найдено)
        - { resource: 'my_other_config_file.xml', ignore_errors: true }
    
    # ...
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <!-- 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
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <imports>
            <import resource="legacy_config.php"/>
            <!-- глобальные выражения также поддерживают загрузку нескольких файлов -->
            <import resource="/etc/myapp/*.yaml"/>
    
            <!-- ignore-errors="not_found" тихо удаляет ошибки в случае если загруженный файл не существует -->
            <import resource="my_config_file.yaml" ignore-errors="not_found"/>
            <!-- ignore-errors="true" тихо удаляет все ошибки (включая неверный код и не найдено) -->
            <import resource="my_other_config_file.yaml" ignore-errors="true"/>
        </imports>
    
        <!-- ... -->
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    // config/services.php
    namespace Symfony\Component\DependencyInjection\Loader\Configurator;
    
    return static function (ContainerConfigurator $container) {
        $container->import('legacy_config.php');
    
        // глобальные выражения также поддерживают загрузку нескольких файлов
        $container->import('/etc/myapp/*.yaml');
    
        // the third optional argument of import() is 'ignore_errors'
        // 'ignore_errors' установленный как 'not_found' silently тихо удаляет ошибки в случае если загруженный файл не существует
        $container->import('my_config_file.yaml', null, 'not_found');
        // 'ignore_errors' тихо удаляет все ошибки (включая неверный код и не найдено)
        $container->import('my_config_file.yaml', null, true);
    };
    
    // ...
    

Параметры конфигурации

Иногда одино и то же значение конфигурации используется в нескольких файлах конфигурации. Вместо его повторения, вы можете определить его как “параметр”, что является чем-то вроде повторно используемого значения конфигурации. По соглашению, параметры определяются под ключом parameters в файле config/services.yaml:

  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    # config/services.yaml
    parameters:
        # имя параметра - произвольная строка (рекомендуется префикс 'app.'
        # для лучшей дифференциации ваших параметров от параметров Symfony).
        app.admin_email: '[email protected]'
    
        # булевы параметры
        app.enable_v2_protocol: true
    
        # параметры массива/коллекции
        app.supported_locales: ['en', 'es', 'fr']
    
        # параметры бинарного содержания (зашифруйте его с помощью base64_encode())
        app.some_parameter: !!binary VGhpcyBpcyBhIEJlbGwgY2hhciAH
    
        # PHP-константы в качестве значений параметра
        app.some_constant: !php/const GLOBAL_CONSTANT
        app.another_constant: !php/const App\Entity\BlogPost::MAX_ITEMS
    
    # ...
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    <!-- 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"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <parameters>
            <!-- имя параметра - произвольная строка (рекомендуется префикс 'app.'
                 для лучшей дифференциации ваших параметров от параметров Symfony). -->
            <parameter key="app.admin_email">[email protected]</parameter>
    
            <!-- булевы параметры -->
            <parameter key="app.enable_v2_protocol">true</parameter>
            <!-- if you prefer to store the boolean value as a string in the parameter -->
            <parameter key="app.enable_v2_protocol" type="string">true</parameter>
    
            <!-- параметры массива/коллекции -->
            <parameter key="app.supported_locales" type="collection">
                <parameter>en</parameter>
                <parameter>es</parameter>
                <parameter>fr</parameter>
            </parameter>
    
            <!-- параметры бинарного содержания (зашифруйте его с помощью base64_encode()) -->
            <parameter key="app.some_parameter" type="binary">VGhpcyBpcyBhIEJlbGwgY2hhciAH</parameter>
    
            <!-- PHP-константы в качестве значений параметра -->
            <parameter key="app.some_constant" type="constant">GLOBAL_CONSTANT</parameter>
            <parameter key="app.another_constant" type="constant">App\Entity\BlogPost::MAX_ITEMS</parameter>
        </parameters>
    
        <!-- ... -->
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    // config/services.php
    namespace Symfony\Component\DependencyInjection\Loader\Configurator;
    
    use App\Entity\BlogPost;
    
    return static function (ContainerConfigurator $container) {
        $container->parameters()
            // имя параметра - произвольная строка (рекомендуется префикс 'app.'
            // для лучшей дифференциации ваших параметров от параметров Symfony).
            ->set('app.admin_email', '[email protected]')
    
            // булевы параметры
            ->set('app.enable_v2_protocol', true)
    
            // параметры массива/коллекции
            ->set('app.supported_locales', ['en', 'es', 'fr'])
    
            // параметры бинарного содержания (используйте упряаляющие последовательности PHP)
            ->set('app.some_parameter', 'This is a Bell char: \x07')
    
            // PHP-константы в качестве значений параметра
            ->set('app.some_constant', GLOBAL_CONSTANT)
            ->set('app.another_constant', BlogPost::MAX_ITEMS);
    };
    
    // ...
    

Caution

При использовании XML-конфигурации, значения между тегами <parameter> не обрезаются. Это означает, что значение следующего параметра будет '\n    something@example.com\n':

1
2
3
<parameter key="app.admin_email">
    [email protected]
</parameter>

Когда он будет определен, вы можете сослаться на значение этого парамтера из любого другого файла конфигурации, используя специальный синтаксис: оберните имя параметра в два % (например, %app.admin_email%):

  • YAML
    1
    2
    3
    4
    5
    6
    # config/packages/some_package.yaml
    some_package:
        # любая строка, окруженная двумя %, заменяется этим значением параметра
        email_address: '%app.admin_email%'
    
        # ...
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    <!-- config/packages/some_package.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
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <!-- любая строка, окруженная двумя %, заменяется этим значением параметра -->
        <some-package:config email-address="%app.admin_email%">
            <!-- ... -->
        </some-package:config>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    // config/packages/some_package.php
    namespace Symfony\Component\DependencyInjection\Loader\Configurator;
    
    return static function (ContainerConfigurator $container) {
        $container->extension('some_package', [
            // любая строка, окруженная двумя %, заменяется этим значением параметра
            'email_address' => '%app.admin_email%',
    
            // ...
        ]);
    };
    

Note

Если какое-то значение параметра включает в себя символ %, вам нужно экранировать его, добавив еще один %, чтобы Symfony не восприняел его в качестве ссылки на имя параметра:

  • YAML
    1
    2
    3
    4
    # config/services.yaml
    parameters:
        # Parsed as 'https://symfony.com/?foo=%s&amp;bar=%d'
        url_pattern: 'https://symfony.com/?foo=%%s&amp;bar=%%d'
    
  • XML
    1
    2
    3
    4
    <!-- config/services.xml -->
    <parameters>
        <parameter key="url_pattern">http://symfony.com/?foo=%%s&amp;bar=%%d</parameter>
    </parameters>
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    // config/services.php
    namespace Symfony\Component\DependencyInjection\Loader\Configurator;
    
    return static function (ContainerConfigurator $container) {
        $container->parameters()
            ->set('url_pattern', 'http://symfony.com/?foo=%%s&amp;bar=%%d');
    };
    

Note

Due to the way in which parameters are resolved, you cannot use them to build paths in imports dynamically. This means that something like the following doesn’t work:

  • YAML
    1
    2
    3
    # config/services.yaml
    imports:
        - { resource: '%kernel.project_dir%/somefile.yaml' }
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    <!-- 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
            https://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <imports>
            <import resource="%kernel.project_dir%/somefile.yaml"/>
        </imports>
    </container>
    
  • PHP
    1
    2
    // config/services.php
    $loader->import('%kernel.project_dir%/somefile.yaml');
    

Параметры конфигурации очень распространены в приложениях Symfony. Некоторые пакет даже определяют свои собственные параметры (например, при установке пакета переводов, в файл config/services.yaml добавляется новый параметр locale).

See also

Позжей в этой статье вы можете прочесть как получать параметры конфигурации в контроллерах и сервисах.

Окружения конфигурации

У вас есть только одно приложение, но понимаете вы это или нет, вам нужно, чтобы оно вело себя по-разному при разных обстоятельствах:

  • Во время разработки, вам нужно вести логи всего и иметь хорошие инструменты отладки;
  • После запуска в производство, вам нужно, чтобы то же приложение было оптимизировано для скорости и вело лог только для ошибок.

Файлы, хранящиеся в config/packages/ используются Symfony для конфигурации сервисов приложения. Другими словами, вы можете изменить поведение приложения, изменив то, какие файлы конфигурации загружаются. В этом заключается идея окружений конфигурации Symfony.

Типичное приложение Symfony начинается с трех окружений: dev (для локальной разработки), prod (для производственных серверов) м test (для автоматизированных тестов). При запуске приложения Symfony загружает файлы конфигурации в этом порядке (последние файлы могут переопределить значения, установленные в предыдущих):

  1. config/packages/*.yaml (а также файлы *.xml и *.php);
  2. config/packages/<environment-name>/*.yaml (а также файлы *.xml и *.php);
  3. config/services.yaml (а также файлы services.xml и services.php);
  4. config/services_<environment-name>.yaml (а также файлы services_<environment-name>.xml и services_<environment-name>.php).

Возьмем пакет framework, установленный по умолчанию, в качетве примера:

  • Вначале загружается config/packages/framework.yaml во всех окружениях и конфигурирует фреймворк с некоторыми опциями;
  • В окружении prod не будет установлено ничего дополнительного, так как нет файла config/packages/prod/framework.yaml;
  • В окружении dev, также нет файла ( config/packages/dev/framework.yaml не существует).
  • В окружении test, файл config/packages/test/framework.yaml загружается для переопределения некоторых из настроек, ранее сконфигурированных в config/packages/framework.yaml.

В реальности, каждое окружение отличается от других совсем немного. Это означает, что все окружения имеют общую базу конфигурации, которая помещает файлы напрямую в каталог config/packages/.

See also

См. также метод configureContainer() класса Kernel, чтобы узнать все о порядке загрузки файлов конфигурации.

Выбор активного окружения

Приложения Symfony имеют файл под названием .env, который находится в корневом каталоге проекта. Этот файл используется для определения значения переменных окружения и детально разъясняется далее в этой статье.

Откройте файл .env file (а лучше файл .env.local, если вы его создавали) и отредактируйте зачение переменной APP_ENV, чтобы изменить окружение, в котором работает приложение. Например, запустите приложение в производстве:

1
2
# .env (или .env.local)
APP_ENV=prod

Это значение используется как для веб-команд, так и для консольных. Однако, вы можете переопределить его для команд, установив значение APP_ENV до их запуска:

1
2
3
4
5
# Используйте окружение, определенное в файле .env
$ php bin/console command_name

# Игнорируйте файл .env file и выполните эту команду в производстве
$ APP_ENV=prod php bin/console command_name

Создание нового окружения

Трех окружений по умолчанию предоставляемых Symfony достаточно для большоинства проектов, но вы также можете определить собственные окружения. Например, вот как вы можете определить окружение staging, где клиент может тестировать проект до его запуска в производство:

  1. Создайте каталог конфигурации с тем же именем, что и у окружения (в этом случае, config/packages/staging/);
  2. Добавьте необходимые файлы конфигурации в config/packages/staging/, чтобы определить поведение нового окружения. Symfony загружает файлы config/packages/*.yaml первыми, поэтому вам нужно сконфигурировать только разницу в этих файлах;
  3. Выберите окружение staging, используя вариант окружения APP_ENV, как объяснялось в предыдущем разделе.

Tip

Окружения часто похожи друг на друга, поэтому вы можете использовать символьные ссылки между каталогами config/packages/<environment-name>/, чтобы повторно использовать одну и ту же конфигурацию.

Конфигурация, основанная на переменных окружаения

Использование `переменных окружения`_ (или сокращенно “env vars”) - это распространенная практика для конфигурации опций, которые зависят от того, где запускается приложение (например, идентификационные данные БД обычно отличаются в производстве и на вашей локальной машине). Если значения чувствительны, вы даже можете зашифровать из как секретные.

Вы можете ссолаться на переменные окружения используя специальный синтаксис %env(ENV_VAR_NAME)%. Значения этих опций разрешаются во время выполнения (только единожды за запрос, чтобы не повлиять на производительность).

Этот пример показывает, как вы можете сконфигурировать соединение БД, используя переменную окружения:

  • YAML
    1
    2
    3
    4
    5
    6
    # config/packages/doctrine.yaml
    doctrine:
        dbal:
            # по соглашению имена переменных окружений всегда используют верхний регистр
            url: '%env(resolve:DATABASE_URL)%'
        # ...
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    <!-- 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
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/doctrine
            https://symfony.com/schema/dic/doctrine/doctrine-1.0.xsd">
    
        <doctrine:config>
            <!-- по соглашению имена переменных окружений всегда используют верхний регистр -->
            <doctrine:dbal url="%env(resolve:DATABASE_URL)%"/>
        </doctrine:config>
    
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    // config/packages/doctrine.php
    namespace Symfony\Component\DependencyInjection\Loader\Configurator;
    
    return static function (ContainerConfigurator $container) {
        $container->extension('doctrine', [
            'dbal' => [
                // по соглашению имена переменных окружений всегда используют верхний регистр
                'url' => '%env(resolve:DATABASE_URL)%',
            ]
        ]);
    };
    

See also

Значения переменных окружения могут быть только строками, но Symfony включает некоторые процессоры env var, чтобы трансформировать их содержание (например, превратить значение строки в целое число).

Чтобы определить значение любой переменной окружения, у вас есть несколько вариантов:

Tip

Некоторые хосты - как SymfonyCloud - предлагают простые в производстве `утилиты для работы с env var`_

Caution

Имейте в виду, что сброс содержания переменных $_SERVER и $_ENV или вывод содержания phpinfo() отобразит значения переменных окружения, обнажая чувствительную информацию вроде идентификационных данных БД.

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

Конфигурация переменных окружения в файлах .env

Вместе определения переменных окружения в вашей оболочке или веб-сервере, Symfony предоставляет удобный способ определить их в файле .env (начинается с точки), расположенном в корне вашего проекта.

Файл .env читается и анализируется при каждом запросе и его переменные окружения добавляются к PHP-переменным $_ENV & $_SERVER. Все существующие переменные окружения никогда не переопределяются значениями, определенными в .env, поэтому вы можете их комбинировать.

Например, чтобы определить переменные окружения DATABASE_URL, показанные ранее в этой статье, вы можете добавить:

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

Этот файл должен быть отправлен в ваше хранилище и (в связи с этим фактом) должег содержать только значения “по умолчанию”, которые подходят для локальной разработки. Этот файл не должен содержать значений производства.

В дополнение к вашим собственным переменным окружения, этот файл .env также содержит переменные окружения, определенные сторонними пакетами, установленными в вашем приложении (они автоматически добавляются Symfony Flex при установке пакетов).

Синтаксис файла .env

Добавляйте комментарии с префиксом #:

1
2
3
# database credentials
DB_USER=root
DB_PASS=pass # это секретный пароль

Используйте переменные окружения в значениях, добавляя к ним префикс $:

1
2
DB_USER=root
DB_PASS=${DB_USER}pass # добавьте пользователя в качестве префикса пароля

Caution

Порядок важен, когда некоторые из переменных окружения зависят от значения других переменных окружения. В примере выше, DB_PASS должен быть определен после DB_USER. Более того, если вы определите несколько файлов .env и первым поставите DB_PASS, его значение будет зависеть от значения DB_USER, определенного в других файлах, вместо значения, определенного в этом файле.

Определите значение по умолчанию в случае, если переменная окружения не установлена:

1
2
DB_USER=
DB_PASS=${DB_USER:-root}pass # results in DB_PASS=rootpass

Встройте команды через $() (не поддерживается в Windows):

1
START_TIME=$(date)

Caution

Использование $() может не работать в зависимости от вашей оболочки.

Tip

Так как файл .env - обычный скрипт оболочки, вы можете source его в ваших собственных скриптах оболочки:

1
$ source .env

Переопределение значений окружения через .env.local

Если вам нужно переопределить значение окружения (например, на другое значение на вашей локальной машине), вы можете сделать то в файле .env.local:

1
2
# .env.local
DATABASE_URL="mysql://root:@127.0.0.1:3306/my_database_name"

Этот файл должен быть проигнорирован git и не должен быть отправлен в ваше хранилище. Несколько других файлов .env доступня для установки переменных окружения только в правильных ситуациях:

  • .env: определяет значения по умолчанию для переменных окружения, которые нужны приложению;
  • .env.local: переопределяет значения по умолчанию для всех окружений, но только на машине, содержащей этот файл. Этот файл не должен быть отправлен в хранилище, и он игнорируется в окружении test (так как тесты должны производить одинаковые результаты для всех);
  • .env.<environment> (напиример, .env.test): пеоепределяет переменные окружения только для одного окружения, но для всех машин (эти файлы отправляются);
  • .env.<environment>.local (напиример, .env.test.local): опрелеяет переменные окружения, относящиеся к конкретной машине, пеоеопределяя их только для одного окружения. Похоже на .env.local, но переопределения применяются только к одному окружению.

Настоящие переменные окружения всегда выигрывают у тех, которые созданы любым файлом .env.

Файлы .env и .env.<environment> не должны быть отправлены в хранилище, так как они одинаковы для всех разработчиков и машин. Однако, файлы env, заканчивающиеся на .local (.env.local и .env.<environment>.local) не должны быть отправлены, так как их будете использовать только вы. На самом деле, файл .gitignore, который поставляется с Symfony, предотвращает их от отправки.

Caution

Приложения, созданные до ноября 2018 года, имели немного другую систему, включающую в себя файл .env.dist. Чтобы узнать об обновлении, см.: Nov 2018 Changes to .env & How to Update.

Конфигурация переменных окружения в производстве

В производстве, файлы .env также анализируются и загружаются по каждому запросу. Поэтому самый простой способ определить переменные окружения - развернуть файл .env.local на вашем производственном сервере(ах) с вашими значениями производства.

Для улучшения производительности, вы можете по желанию выполнить команду dump-env (доступна в Symfony Flex 1.2 и позже):

1
2
# анализирует ВСЕ файлы .env и сбрасывает их финальные значения в .env.local.php
$ composer dump-env prod

После выполнения этой команды, Symfony загрузит файл .env.local.php, чтобы получить пременные окружения и не будет тратить время, анализируя файлы .env.

Tip

Обновите свои инструменты развертывания/рабочего процесса, чтобы выполнять команду dump-env после каждого рвазвертывания, чтобы улучшить производительность приложения.

Шифрование переменных окружения (секреты)

Вместо определения реальной переменной окружения или ее добавления в файл .env, если значение переменной чувствительно (например, ключ API или пароль БД), вы можете зашифровать значение, используя систему управления секретами.

Перечень переменных окружения

Независимо от того, как вы устанавливаете переменные окружения, вы можете увидеть полный список с их значениями, запустив:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$ php bin/console debug:container --env-vars

---------------- ----------------- ---------------------------------------------
 Name             Default value     Real value
---------------- ----------------- ---------------------------------------------
 APP_SECRET       n/a               "471a62e2d601a8952deb186e44186cb3"
 FOO              "[1, "2.5", 3]"   n/a
 BAR              null              n/a
---------------- ----------------- ---------------------------------------------

# вы также можете отфильтровать список env vars по имени:
$ php bin/console debug:container --env-vars foo

# выполните эту команду, чтобы показать все детали для конкретного env var:
$ php bin/console debug:container --env-var=FOO

Доступ к параметрам конфигурации

Контроллеры и сервисы могут получить доступ ко всем параметрам конфигурации. Это включает в себя как параметры, определенные вами defined by yourself, так и параметры, созданные пакетами. Выполните следующую команду, чтобы увидеть все параметры, существующие в вашем приложении:

1
$ php bin/console debug:container --parameters

В контроллерах, расщиряющихся из AbstractController, используйте хелпер getParameter():

// src/Controller/UserController.php
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;

class UserController extends AbstractController
{
    // ...

    public function index(): Response
    {
        $projectDir = $this->getParameter('kernel.project_dir');
        $adminEmail = $this->getParameter('app.admin_email');

        // ...
    }
}

В сервисах и контроллерах, не расширяющихся из AbstractController, внедрите параметры в качестве аргументов их конструкторов. Вы должены внедрить их ясно, потому что автоматическое внедрение сервисов не работает для параметров:

  • YAML
    1
    2
    3
    4
    5
    6
    7
    8
    # config/services.yaml
    parameters:
        app.contents_dir: '...'
    
    services:
        App\Service\MessageGenerator:
            arguments:
                $contentsDir: '%app.contents_dir%'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    <!-- 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
            https://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <parameters>
            <parameter key="app.contents_dir">...</parameter>
        </parameters>
    
        <services>
            <service id="App\Service\MessageGenerator">
                <argument key="$contentsDir">%app.contents_dir%</argument>
            </service>
        </services>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    // config/services.php
    namespace Symfony\Component\DependencyInjection\Loader\Configurator;
    
    use App\Service\MessageGenerator;
    
    return static function (ContainerConfigurator $container) {
        $container->parameters()
            ->set('app.contents_dir', '...');
    
        $container->services()
            ->get(MessageGenerator::class)
                ->arg('$contentsDir', '%app.contents_dir%');
    };
    

Если вы будете внедрять одни и те же параметры снова и снова, используйте вместо этого опцию services._defaults.bind. Аргументы, определенные в этой опции, внедряются автоматически каждый раз, когда конструктор сервиса или действие контроллера определяет аргумент с точно таким же именем. Например, чтобы внедрять значение параметра kernel.project_dir, каждый раз, когда сервис/контроллер определяет аргумент $projectDir, используйте это:

  • YAML
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # config/services.yaml
    services:
        _defaults:
            bind:
                # передайте это значение любому аргументу $projectDir для любого сервиса,
                # созданного в этом файле (включая аргументы контроллера)
                $projectDir: '%kernel.project_dir%'
    
        # ...
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    <!-- 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
            https://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <services>
            <defaults autowire="true" autoconfigure="true" public="false">
                <!-- передайте это значение любому аргументу $projectDir для любого сервиса,
                     созданного в этом файле (включая аргументы контроллера) -->
                <bind key="$projectDir">%kernel.project_dir%</bind>
            </defaults>
    
            <!-- ... -->
        </services>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    // config/services.php
    namespace Symfony\Component\DependencyInjection\Loader\Configurator;
    
    use App\Controller\LuckyController;
    
    return static function (ContainerConfigurator $container) {
        $container->services()
            ->defaults()
                // передайте это значение любому аргументу $projectDir для любого сервиса,
                // созданного в этом файле (включая аргументы контроллера)
                ->bind('$projectDir', '%kernel.project_dir%');
    
        // ...
    };
    

See also

Прочтите статью об объединении аргументов по имени и/или типу, чтобы узнать больше об этой мощной функции.

Наконец, если какому-то сервису нужен доступ ко множеству параметров, вместо внедрения каждого из них отдельно, вы можете внедрить все параметры приложения одномоментно добавив подсказки при вводе кода к любому из аргументов конструктора с ContainerBagInterface:

// src/Service/MessageGenerator.php
namespace App\Service;

// ...

use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface;

class MessageGenerator
{
    private $params;

    public function __construct(ContainerBagInterface $params)
    {
        $this->params = $params;
    }

    public function someMethod()
    {
        // получите любой параметр контейнера из $this->params, который хранит их все
        $sender = $this->params->get('mailer_sender');
        // ...
    }
}

Использование PHP ConfigBuilders

New in version 5.3: Функция “ConfigBuilders” была представлена в Symfony 5.3 в качестве экспериментальной функции.

Написание PHP-конфигурации иногда бывает сложным, потому что у вас получаются большие вложенные массивы, и у вас нет помощи в автозаполнении из вашего любимого IDE. Это можно решить с помощью “ConfigBuilders”. Это объекты, которые помогут вам строить эти массивы.

Symfony генерирует классы ConfigBuilder автоматически в каталоге строения ядра для всех пакетов, установленных в вашем приложении. По соглашению, они все живут в пространстве имен Symfony\Config:

// config/packages/security.php
use Symfony\Config\SecurityConfig;

return static function (SecurityConfig $security) {
    $security->firewall('main')
        ->pattern('^/*')
        ->lazy(true)
        ->anonymous();

    $security
        ->roleHierarchy('ROLE_ADMIN', ['ROLE_USER'])
        ->roleHierarchy('ROLE_SUPER_ADMIN', ['ROLE_ADMIN', 'ROLE_ALLOWED_TO_SWITCH'])
        ->accessControl()
            ->path('^/user')
            ->role('ROLE_USER');

    $security->accessControl(['path' => '^/admin', 'roles' => 'ROLE_ADMIN']);
};

Note

Только корневые классы в пространстве имен Symfony\Config являются ConfigBuilders. Вложенные конфигурации (например, \Symfony\Config\Framework\CacheConfig) являются обычными PHP-объектами, которые не внедряются автоматически во время их использования в качестве типа аргумента.

Не останавливайтесь!

Поздравляем ! Вы справились с основами Symfony. Далее, узнайте о каждой части Symfony отдельно, cледуя руководствами. Посмотрите:

И все другие темы, связанные с конфигурацией:

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