in Профессиональное

Symfony 2: конфигурирование пакетов

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

Простая конфигурация

Для простой конфигурации можно воспользоваться разделом parameters, по-умолчанию присутствующим в конфигурации Symfony2. Параметры – это простые пары ключ-значение; значением может быть любое валидное значение с точки зрения PHP. Каждое наименование параметра должно начинаться с наименования пакета в нижнем регистре (hello для HelloBundle, или sensio.social.blog для SensioSocialBlogBundle).

Пользователь может задавать значения в любом конфигурационном файле:

  • YAML
    # app/config/config.yml
    parameters:
        hello.email.from: fabien@example.com
  • XML
    <!-- app/config/config.xml -->
    <parameters>
        <parameter key="hello.email.from">fabien@example.com</parameter>
    </parameters>
  • PHP
    // app/config/config.php
    $container->setParameter('hello.email.from', 'fabien@example.com');
  • INI
    [parameters]
    hello.email.from = fabien@example.com

Получить параметры в коде можно из контейнера:

$container->getParameter('hello.email.from');

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

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

Семантическая конфигурация имеет бОльшую гибкость в конфигурировании пакетов и превосходит простые параметры по следующим показателям:

  • Возможность определить больше чем просто параметры (например сервисы);
  • Лучшая иерархия в конфигурации (вы можете определять вложенные конфигурации);
  • “Умные” слияния (merging), когда несколько файлов конфигурации переопределяют существующую конфигурацию;
  • Валидация конфигурации (если вы определите XSD файл и используете XML);
  • Завершение при использовании XSD и XML (прим. пер: видимо тут имеется в виду автозавершение в IDE на основе XSD структуры XML)

Создание расширения (Extension)

Для того чтобы использовать семантическую конфигурацию, создайте расширение Dependency Injection, которое наследуется от Extension:

// HelloBundle/DependencyInjection/HelloExtension.php
use SymfonyComponentDependencyInjectionExtensionExtension;

class HelloExtension extends Extension
{
    public function configLoad($config, ContainerBuilder $container)
    {
        // ...
    }

    public function getXsdValidationBasePath()
    {
        return __DIR__.'/../Resources/config/';
    }

    public function getNamespace()
    {
        return 'http://www.example.com/symfony/schema/';
    }

    public function getAlias()
    {
        return 'hello';
    }
}

Класс, описанный выше определяет пространство имен hello:config, доступное в любом конфигурационном файле:

  • YAML
    # app/config/config.yml
    hello.config: ~
  • XML
    <!-- app/config/config.xml -->
    <?xml version="1.0" ?>
    
    <container xmlns="http://www.symfony-project.org/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:hello="http://www.example.com/symfony/schema/"
        xsi:schemaLocation="http://www.example.com/symfony/schema/ http://www.example.com/symfony/schema/hello-1.0.xsd">
    
       <hello:config />
       ...
    
    </container>
  • PHP
    // app/config/config.php
    $container->loadFromExtension('hello', 'config', array());
Замечание: вы можете создать столько методов xxxLoad(), сколько хотите определить конфигурационных блоков для вашего расширения.

Разбор конфигурации

Всякий раз, когда пользователь включает пространство имен hello.config в конфигурационный файл, вызывается метод configLoad() вашего расширения и конфигурация передается в виде массива (Symfony2 автоматически конвертирует XML и YAML в массивы).

Итак, мы имеем следующую конфигурацию:

  • YAML
    # app/config/config.yml
    hello.config:
        foo: foo
        bar: bar
  • XML
    <!-- app/config/config.xml -->
    <?xml version="1.0" ?>
    
    <container xmlns="http://www.symfony-project.org/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:hello="http://www.example.com/symfony/schema/"
        xsi:schemaLocation="http://www.example.com/symfony/schema/ http://www.example.com/symfony/schema/hello-1.0.xsd">
    
        <hello:config foo="foo">
            <hello:bar>foo</hello:bar>
        </hello:config>
    
    </container>
  • PHP
    // app/config/config.php
    $container->loadFromExtension('hello', 'config', array(
        'foo' => 'foo',
        'bar' => 'bar',
    ));

Массив, который будет передаваться в ваш метод будет таким:

array(
    'foo' => 'foo',
    'bar' => 'bar',
)

Внутри метода configLoad() переменная $container ссылается на контейнер, который знает лишь об этом пространстве имен. Вы можете манипулировать добавлением сервисов и параметров в нужном вам направлении. Когда метод вызывается первый раз, контейнер знает лишь о глобальных параметрах. При последующих вызовах он содержит конфигурацию, определенную предыдущими вызовами. Таким образом метод должен объединить новые настройки со старыми:

// only load default services and parameters once
if (!$container->hasDefinition('xxxxx')) {
    $loader = new XmlFileLoader($container, __DIR__.'/../Resources/config');
    $loader->load('hello.xml');
}

Глобальные параметры:

  • kernel.name
  • kernel.environment
  • kernel.debug
  • kernel.root_dir
  • kernel.cache_dir
  • kernel.logs_dir
  • kernel.bundle_dirs
  • kernel.bundles
  • kernel.charset
Предупреждение: все имена параметров и сервисов, начинающиеся с подчерка (_) зарезервированы для использования фреймворком и новые не должны определяться в пакетах.

Соглашения по созданию расширений

При создании расширения следуйте этим простым соглашениям:

  • Расширение должно находиться во вложенном пространстве имен DependencyInjection;
  • Расширение должно именоваться при помощи наименования пакета и завершаться суффиксом Extension (HelloExtension для HelloBundle) – если же вы создаете несколько расширений для одного пакета, просто завершайте их суффиксом Extension;
  • Алиас должен быть уникальным и должен именоваться также при помощи наименования пакета (hello для HelloBundle или sensio.social.blog для SensioSocialBlogBundle);
  • Расширение должно содержать XSD схему.

Если вы последуете этим рекомендациям, то ваше расширение автоматически будет зарегистрировано Symfony2. Если этого не произошло, переопределите метод пакета registerExtensions():

class HelloBundle extends Bundle
{
    public function registerExtensions(ContainerBuilder $container)
    {
        // register the extension(s) found in DependencyInjection/ directory
        parent::registerExtensions($container);

        // register extensions that do not follow the conventions manually
        $container->registerExtension(new ExtensionHello());
    }
}

Конфигурация по-умолчанию

Как определено ранее, пользователь пакета должен включить пространство имен hello.config в конфигурационный файл, для того чтобы вызывался код вашего расширения. Но вы также можете автоматически регистрировать конфигурацию по-умолчанию, переопределяя метод пакета registerExtensions():

class HelloBundle extends Bundle
{
    public function registerExtensions(ContainerBuilder $container)
    {
        // will register the HelloBundle extension(s) found in DependencyInjection/ directory
        parent::registerExtensions($container);

        // load some defaults
        $container->loadFromExtension('hello', 'config', array(/* your default config for the hello.config namespace */));
    }
}

Внимание: Symfony2 старается быть максимально открытым и понятным. Поэтому определение конфигурации по-умолчанию автоматически это наверняка не очень хорошая идея.

Оригинал тут: http://docs.symfony-reloaded.org/guides/bundles/configuration.html

Перевод как всегда – мой авторский ))

Write a Comment

Comment

*

  1. Спасибо за переводы. А нет ли желания какую-нить статейку про свой опыт использования сф2 сделать?

    • До релиза symfony2 наверное нет. Не хочу ничего серьезно на него портировать пока нет стабильной версии. Ну или с нуля делать. Да и понимания пока хорошего нет, в частности поэтому и перевожу – сам же потом читать буду )

    • Статью можно сливать, уже совершенно не актуально =)

  2. А мы вот начали делать крупный проект на symfony2. Раньше хотели на sf1.x, но передумали.
    Трахаться приходится изрядно, но очень нравится новое!
    Twig вообще офигительная вещь!

    • Ну… я можно сказать его немного побаиваюсь… (( Вот и медлю…