Как освоить и создавать новые окружения

Каждое приложение - это комбинация кода и набора конфигурации, которая диктует, как должен функционировать код. Конфигурация может определять используемую БД, нужно ли что-либо кешировать или степень многословности ведения записи логов.

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

Разные окружения, разные файлы конфигурации

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

  • для окружения dev: app/config/config_dev.yml
  • для окружения prod: app/config/config_prod.yml
  • для окружения test: app/config/config_test.yml

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// app/AppKernel.php

// ...

class AppKernel extends Kernel
{
    // ...

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

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

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

  • YAML
    1
    2
    3
    4
    imports:
        - { resource: config.yml }
    
    # ...
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    <?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">
    
        <imports>
            <import resource="config.xml" />
        </imports>
    
        <!-- ... -->
    
    </container>
    
  • PHP
    1
    2
    3
    $loader->import('config.php');
    
    // ...
    

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

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

Выполнение приложения в разных окружениях

Чтобы выполнить приложение в каждом окружении, загрузите его, используя либо фронт-контроллер app.php (для окружения prod), либо app_dev.php (для окружения dev):

1
2
http://localhost/app.php      -> окружение *prod*
http://localhost/app_dev.php  -> окружение *dev*

Если у вас нет ни одного имени файла в вашем URL, то тогда ваш веб-сервер за кулисами решает, какой файл выполнять. Если вы используете встроенный PHP веб-сервсер, то он знает, что надо использовать файл app_dev.php. В производстве вы сконфигурируете ваш веб-сервер так, чтобы он использовал app.php. В любом случае: один из этих двух файлов всегда выполняется.

Note

Данные URL предполагают, что ваш веб-сервер сконфигурирован так, чтобы использовать каталог приложение web/ в качестве корневого. Прочтите больше в Установке Symfony.

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

1
2
3
4
5
6
// web/app.php
// ...

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

// ...

Ключ prod указывает на то, что это приложение будет запущено в окружении prod. Приложение Symfony может быть выполнено в любом окружении путём использования этого кода и изменения строки окружения.

Note

Окружение test используется при написании функциональных тестов и оно недоступно в браузере напрямую через фронт-контроллер. Другими словами, в отличие от других окружений, файла фронт-контроллера app_test.php нет.

Важным, но не имеющим отношения к теме окружений, являетсяаргумент false в качестве второго аргумента конструктора AppKernel. Он указывает, должно ли приложеие работать в "режиме отладки". Несмотря на окружение, приложение Symfony может быть запущено с режимом отладки, установленным как true или false. Это влияет на многие вещи в приложении, такие как отображение трассы высовов в стеке на страницах ошибки или на динамическую перестройку файлов кеша по каждому запросу. Хоть это и не является требование, режим отлабки обычно установлен как true для окружений dev и test, и как false для окружения prod.

Внутренне, значение режима отладки становится параметром kernel.debug, используемым внутри сервис-контейнера. Если вы посмотрите внутрь файла конфигурации приложения, вы увидите, что используемый параметр, например, включает и выключаете ведение логов при испошльзовании Doctrine DBAL:

  • YAML
    1
    2
    3
    4
    doctrine:
       dbal:
           logging: '%kernel.debug%'
           # ...
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    <?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:dbal logging="%kernel.debug%" />
    
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    $container->loadFromExtension('doctrine', array(
        'dbal' => array(
            'logging'  => '%kernel.debug%',
            // ...
        ),
        // ...
    ));
    

Выбор окружения для консольных команд

По умолчанию, команды Symfony выполняются в окружении dev с включенным режимом отладки. Используйте опции --env и --no-debug, чтобы настроить это поведение:

1
2
3
4
5
6
7
8
# окружение 'dev', отладка включена
$ php bin/console command_name

# окружение 'prod' (отладка всегда отключена для 'prod')
$ php bin/console command_name --env=prod

# окружение 'test', отладка выключена
$ php bin/console command_name --env=test --no-debug

В дополнение к опциям --env и --no-debug, поведение команд Symfony также можно контролировать с помощью переменных окружения. Консольное приложение Symfony проверяет наличие и значение этих переменных окружения до выполнения любой команды:

SYMFONY_ENV
Устанаваливает окружение выполнения команды в значение этой перменной (dev, prod, test, и т.д.);
SYMFONY_DEBUG
Если 0, то режим отладки отключен. В других случаях - включен.

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

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

По умолчанию, приложение Symfony имеет три окружения, которые обрабатывают большинство случаев. Конечно, так как окружение - это не более, чем строка, соответствующая набору конфигурации, то создание нового окружения достаточно лёгкое.

Представьте, к примеру, что перед развёртыванием вам нужно провести сравнительный тест вашего приложения. Одним способом проведения сравнения вашего приложения является использование около-производственных настроек с включённым web_profiler Symfony. Это позволяет Symfony записывать информацию о вашем приложени во время проведения сравнительного теста.

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

  • YAML
    1
    2
    3
    4
    5
    6
    # app/config/config_benchmark.yml
    imports:
        - { resource: config_prod.yml }
    
    framework:
        profiler: { only_exceptions: false }
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <!-- app/config/config_benchmark.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">
    
        <imports>
            <import resource="config_prod.xml" />
        </imports>
    
        <framework:config>
            <framework:profiler only-exceptions="false" />
        </framework:config>
    
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    // app/config/config_benchmark.php
    $loader->import('config_prod.php');
    
    $container->loadFromExtension('framework', array(
        'profiler' => array('only_exceptions' => false),
    ));
    

С помощью этого простого добавления, приложение теперь поддерживает новое окружение под названием benchmark.

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

Так как вы захотите, чтобы к этому окружению можно было получить доступ через браущер, вы должны также создать для него фронт-контроллер. Скопируйте файл web/app.php в web/app_benchmark.php и измените окружение на benchmark:

1
2
3
4
5
6
7
// web/app_benchmark.php
// ...

// измените только эту строку
$kernel = new AppKernel('benchmark', false);

// ...

Новое кружение теперь доступно через:

1
http://localhost/app_benchmark.php

Note

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

1
2
3
if (!in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', '::1'))) {
    die('Вы не имеете доступа к этому файлу. Смотрите '.basename(__FILE__).', чтобы узнать больше.');
}

Окружения и каталог кеша

Symfony во многом пользуется преимуществами кеширования: конфигурация приложения, конфигурация маршрутизации, шаблоны Twig и многое другое кешируется в PHP-объекты, хранящиеся в файлах файловой системы.

По умолчанию, эти кешированные файлы в основном хранятся в каталоге var/cache. Однако, каждое окружение кеширует свой собственный набор файлов:

1
2
3
4
5
6
your-project/
├─ var/
│  ├─ cache/
│  │  ├─ dev/   # cache directory for the *dev* environment
│  │  └─ prod/  # cache directory for the *prod* environment
│  ├─ ...

Иногда при отладке может быть полезным инспектировать кешированный файл, чтобы понять, как что-то работает. Если будете так делать, не забудьте посмотреть в каталог окружения, которое вы используете (чаще всего devпри разработке и отладке). Несмотря на возможные различия, каталог var/cache/dev включает в себя следующее:

appDevDebugProjectContainer.php
Кешированный "сервис-контейнер", который представляет кешированную конфигурацию приложения.
appDevUrlGenerator.php
PHP-класс сгенерированный из конфигурации маршрутизации и используемый при генерировании URL.
appDevUrlMatcher.php
PHP-класс, используемый для сопоставления маршрутов - смотрите сюда, чтобы увидеть скомпилированную логику регулярных выражений, используемую для сопоставления входящих URL с разными маршрутами.
twig/
Этот каталог кодержит все кешированные шаблоны Twig.

Note

Вы можете с лёгкостью изменить локацию и имя каталога. Чтобы узнать больше, прочтите статью How to Override Symfony's default Directory Structure.

Дальнейшее продвижение

Прочтите статью о How to Set external Parameters in the Service Container.

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