Как организовать файлы конфигурации

По умолчанию, стандартная версия Symfony определяет три окружения выполнения, которые называются dev, prod и test. Окружение просто представляет собой способ выполнить одну и ту же кодовую базу с разными конфигурациями.

Для того, чтобы выбрать, какой файл конфигурации загружать для каждого окружения, Symfony выполняет метод registerContainerConfiguration() класса AppKernel:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// app/AppKernel.php
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;

class AppKernel extends Kernel
{
    // ...

    public function registerContainerConfiguration(LoaderInterface $loader)
    {
        $loader->load($this->getProjectDir().'/app/config/config_'.$this->getEnvironment().'.yml');
    }
}

Этот метод загружает файл app/config/config_dev.yml для окружения dev и так далее. В свою очередь, этот файл загружает общий файл конфигурации, расположенный в app/config/config.yml. Следовательно, файлы конфигурации стандартной версии Symfony по умолчанию следуют такой структуре:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
your-project/
├─ app/
│  ├─ ...
│  └─ config/
│     ├─ config.yml
│     ├─ config_dev.yml
│     ├─ config_prod.yml
│     ├─ config_test.yml
│     ├─ parameters.yml
│     ├─ parameters.yml.dist
│     ├─ routing.yml
│     ├─ routing_dev.yml
│     └─ security.yml
├─ ...

Эта структура по умолчанию была выбрана за её простоту - один файл в одном окружении. Но как и любую другую функцию Symfony вы можете настроить её так, чтобы она больше подходила под ваши потребности. Следующие разделы поясняют разные способы организовать ваши файлы конфигурации. Для того, чтобы упростить примеры, рассматриваются только окружения dev и prod.

Разные каталоги в окружениях

Вместо того, чтобы добавлять к файлам суффиксы _dev и _prod, эта техника группирует все связанные файлы конфигурации в одном каталоге с таким же именем, как и окружение:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
your-project/
├─ app/
│  ├─ ...
│  └─ config/
│     ├─ common/
│     │  ├─ config.yml
│     │  ├─ parameters.yml
│     │  ├─ routing.yml
│     │  └─ security.yml
│     ├─ dev/
│     │  ├─ config.yml
│     │  ├─ parameters.yml
│     │  ├─ routing.yml
│     │  └─ security.yml
│     └─ prod/
│        ├─ config.yml
│        ├─ parameters.yml
│        ├─ routing.yml
│        └─ security.yml
├─ ...

Чтобы это работало, измените код метода registerContainerConfiguration():

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// app/AppKernel.php
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;

class AppKernel extends Kernel
{
    // ...

    public function registerContainerConfiguration(LoaderInterface $loader)
    {
        $loader->load($this->getProjectDir().'/app/config/'.$this->getEnvironment().'/config.yml');
    }
}

Далее, убелитесь, что каждый файл config.yml загружает остальные файлы конфигураци, включая общие файлы. Например, вот необходимые импортируемые для файла app/config/dev/config.yml:

  • YAML
    1
    2
    3
    4
    5
    6
    7
    # app/config/dev/config.yml
    imports:
        - { resource: '../common/config.yml' }
        - { resource: 'parameters.yml' }
        - { resource: 'security.yml' }
    
    # ...
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    <!-- app/config/dev/config.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
            http://symfony.com/schema/dic/symfony
            http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <imports>
            <import resource="../common/config.xml" />
            <import resource="parameters.xml" />
            <import resource="security.xml" />
        </imports>
    
        <!-- ... -->
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    // app/config/dev/config.php
    $loader->import('../common/config.php');
    $loader->import('parameters.php');
    $loader->import('security.php');
    
    // ...
    

Семантические файлы конфигурации

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
your-project/
├─ app/
│  ├─ ...
│  └─ config/
│     ├─ bundles/
│     │  ├─ bundle1.yml
│     │  ├─ bundle2.yml
│     │  ├─ ...
│     │  └─ bundleN.yml
│     ├─ environments/
│     │  ├─ common.yml
│     │  ├─ dev.yml
│     │  └─ prod.yml
│     ├─ routing/
│     │  ├─ common.yml
│     │  ├─ dev.yml
│     │  └─ prod.yml
│     └─ services/
│        ├─ frontend.yml
│        ├─ backend.yml
│        ├─ ...
│        └─ security.yml
├─ ...

Опять, измените код метода registerContainerConfiguration(), чтобы уведомить Symfony о новой организации файлов:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// app/AppKernel.php
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;

class AppKernel extends Kernel
{
    // ...

    public function registerContainerConfiguration(LoaderInterface $loader)
    {
        $loader->load($this->getProjectDir().'/app/config/environments/'.$this->getEnvironment().'.yml');
    }
}

Следуя той же технике, что была описана выше, убедитесь, что вы импортируете соответствующие файлы конфигурации из основного файла (common.yml, dev.yml и prod.yml).

Продвинутые техники

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

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

Файлы конфигурации могут импортировать файлы, определённые любым другим встроенным форматом конфигурации (.yml, .xml, .php, .ini):

  • YAML
    1
    2
    3
    4
    5
    6
    7
    8
    # app/config/config.yml
    imports:
        - { resource: 'parameters.yml' }
        - { resource: 'services.xml' }
        - { resource: 'security.yml' }
        - { resource: 'legacy.php' }
    
    # ...
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <!-- app/config/config.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
            http://symfony.com/schema/dic/symfony
            http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <imports>
            <import resource="parameters.yml" />
            <import resource="services.xml" />
            <import resource="security.yml" />
            <import resource="legacy.php" />
        </imports>
    
        <!-- ... -->
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    // app/config/config.php
    $loader->import('parameters.yml');
    $loader->import('services.xml');
    $loader->import('security.yml');
    $loader->import('legacy.php');
    
    // ...
    

Caution

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

Если вы используете любой другой формат конфигурации, вам нужно определить собственный класс загрузчика, расширив его из FileLoader. Когда значения конфигурации динамические, вы можете использовать файл PHP конфигурации, чтобы выполнять собственную логику. Кроме того, вы можете определять ваши собственные сервисы для загрузки конфигураций из баз данных или веб-сервисов.

Глобальные файлы конфигурации

Некоторые системные администраторы предпочитают хранить чувствительные параметры в файлах вне каталога проекта. Предсьавьте, что учетные данные БД для вашего сайта хранятся в файле /etc/sites/mysite.com/parameters.yml. Загрузка этого файла просто заключается в указании полного пути файла при его импорте из любого другого файла конфигурации:

  • YAML
    1
    2
    3
    4
    5
    6
    # app/config/config.yml
    imports:
        - { resource: 'parameters.yml' }
        - { resource: '/etc/sites/mysite.com/parameters.yml' }
    
    # ...
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    <!-- app/config/config.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
            http://symfony.com/schema/dic/symfony
            http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <imports>
            <import resource="parameters.yml" />
            <import resource="/etc/sites/mysite.com/parameters.yml" />
        </imports>
    
        <!-- ... -->
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    // app/config/config.php
    $loader->import('parameters.yml');
    $loader->import('/etc/sites/mysite.com/parameters.yml');
    
    // ...
    

В большнстве случаев, локальные разработчики не будут иметь таких же файлов, существующих на серверах производства. По этой причине, компонент Config предоставляет опцию ignore_errors, чтобы тихо сбрасывать ошибки, когда загруженный файл не существует:

  • YAML
    1
    2
    3
    4
    5
    6
    # app/config/config.yml
    imports:
        - { resource: 'parameters.yml' }
        - { resource: '/etc/sites/mysite.com/parameters.yml', ignore_errors: true }
    
    # ...
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    <!-- app/config/config.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
            http://symfony.com/schema/dic/symfony
            http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <imports>
            <import resource="parameters.yml" />
            <import resource="/etc/sites/mysite.com/parameters.yml" ignore-errors="true" />
        </imports>
    
        <!-- ... -->
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    // app/config/config.php
    $loader->import('parameters.yml');
    $loader->import('/etc/sites/mysite.com/parameters.yml', null, true);
    
    // ...
    

Как вы увидели, существует множество способов организовать ваши файлы конфигурации. Вы можете выбрать один из них или даже создать ваш собственный способ организации файлов. Не чувствуйте себя ограниченными стандартной версией Symfony. Для еще более детального настраивания, смотрите "How to Override Symfony's default Directory Structure".

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