Как сконфигурировать сервис с помощью конфигуратора

Как сконфигурировать сервис с помощью конфигуратора

Конфигуратор сервиса - это функция сервис-контейнера, которая позволяет вам использовать вызываемое, чтобы сконфигурировать сервис после его инстанциирования.

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

Ещё один пример использования - когда у вас есть множество объектов, которые совместно используют общую конфигурацию, или которые должны быть похожим образом сконфигурированы во время прогона.

Например, представьте, что у вас есть приложение, где вы оправляtnt разные виды электронных писем пользователям. Письма пропускаются через различные программы форматирования, которые могут быть включены или нет, в зависимости от некоторых динамических установок приложения. Вы начинаете определять класс NewsletterManager таким образом:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// src/AppBundle/Mail/NewsletterManager.php
namespace AppBundle\Mail;

class NewsletterManager implements EmailFormatterAwareInterface
{
    private $enabledFormatters;

    public function setEnabledFormatters(array $enabledFormatters)
    {
        $this->enabledFormatters = $enabledFormatters;
    }

    // ...
}

а также класс GreetingCardManager:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// src/AppBundle/Mail/GreetingCardManager.php
namespace AppBundle\Mail;

class GreetingCardManager implements EmailFormatterAwareInterface
{
    private $enabledFormatters;

    public function setEnabledFormatters(array $enabledFormatters)
    {
        $this->enabledFormatters = $enabledFormatters;
    }

    // ...
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// src/AppBundle/Mail/EmailFormatterManager.php
namespace AppBundle\Mail;

class EmailFormatterManager
{
    // ...

    public function getEnabledFormatters()
    {
        // код для конфигурации того, какие программы форматирования использовать
        $enabledFormatters = array(...);

        // ...

        return $enabledFormatters;
    }
}

Если вашей целью является избежать объединения NewsletterManager и GreetingCardManager с EmailFormatterManager, то вы можете захотеть создать класс конфигуратора для конфигурирования этих экземпляров:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// src/AppBundle/Mail/EmailConfigurator.php
namespace AppBundle\Mail;

class EmailConfigurator
{
    private $formatterManager;

    public function __construct(EmailFormatterManager $formatterManager)
    {
        $this->formatterManager = $formatterManager;
    }

    public function configure(EmailFormatterAwareInterface $emailManager)
    {
        $emailManager->setEnabledFormatters(
            $this->formatterManager->getEnabledFormatters()
        );
    }

    // ...
}

Работа EmailConfigurator - внедрять включённые программы форматирования в NewsletterManager и GreetingCardManager, потому что они не знают, откуда появились включённые программы форматирования. С другой стороны, EmailFormatterManager содержит данные о включенных программах форматирования и о том, как их загружать, поддерживая единый принцип ответственности.

Tip

В то время, как этот пример использует метод PHP-класса, конфигураторы могут быть любым PHP-вызываемым, включая функции, статические методы и методы сервисов.

Исползование конфигуратора

Вы можете сконфигурировать конфигуратор сервиса, используя опцию configurator. Если вы используете конфигурацию services.yml по умолчанию , то все классы уже загружены как сервисы. Всё, что вам нужно сделать, это точно определить configurator:

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# app/config/services.yml
services:
    # ...

    # Регистрирует все 4 класса как сервисы, включая AppBundle\Mail\EmailConfigurator
    AppBundle\:
        resource: '../../src/AppBundle/*'
        # ...

    # переопределить сервисы, чтобы установить конфигуратор
    AppBundle\Mail\NewsletterManager:
        configurator: 'AppBundle\Mail\EmailConfigurator:configure'

    AppBundle\Mail\GreetingCardManager:
        configurator: 'AppBundle\Mail\EmailConfigurator:configure'

3.2

Синтаксис service_id:method_name для конфигурации формата YAML был представлен в Symfony 3.2.

Традиционный синтаксис конфигуратора в YAML-файлах использовал массив, чтобы определить id сервиса и имя метода:

1
2
3
4
5
app.newsletter_manager:
    # новый синтаксис
    configurator: 'AppBundle\Mail\EmailConfigurator:configure'
    # старый синтаксис
    configurator: ['@AppBundle\Mail\EmailConfigurator', configure]

Вот и всё! При запрашивании сервиса AppBundle\Mail\NewsletterManager или AppBundle\Mail\GreetingCardManager, созданный экземпляр вначале будет передан в метод EmailConfigurator::configure().