преамбула
Мое приложение Symfony2 будет доступно из нескольких доменов верхнего уровня. В зависимости от TLD, я хочу использовать другую почтовую программу. Однако мне не удалось динамически внедрить правильный почтовик, несмотря на множество попыток (фабрика сервисов, проход компилятора, расширение DI, «динамический псевдоним»).
Это приводит к фундаментальной реализации: вводятся зависимости до контейнер скомпилирован, запрос доступен после контейнер скомпилирован. Следовательно, нет способа сделать внедрение зависимостей зависимым от запроса (и, следовательно, все вышеупомянутые подходы потерпели неудачу).
проблема
Мне сказали никогда не тянуть зависимости, а всегда вводить их.
Чтобы проиллюстрировать это далее:
я имею
и хотите ввести правильный Swiftmailer в пользовательский почтовый сервис для FOSUserBundle (или в любой другой сервис, который нуждается в swiftmailer).
Вопрос
Как ввести правильную зависимость, если я не знаю ее, пока запрос не будет доступен?
У меня было две идеи, но я не уверен, насколько они подходят:
Или я совсем не по маршруту?
Внедрение запроса описано в документации. Это, как говорится, я думаю, вы получите максимальную отдачу за доллар используя фабрику.
Для дальнейшего использования, вот реализация Ответ Питера:
Пользовательский почтовик для FOSUserBundle конфигурации:
# app/config/config.yml
fos_user:
# ...
service:
mailer: acme.mailer
а также
# src/Acme/UserBundle/config/services.xml
<service id="acme.mailer.factory" class="Acme\UserBundle\Service\TwigSwiftMailerFactory" public="false">
<call method="setContainer">
<argument type="service" id="service_container" />
</call>
</service>
<service id="acme.mailer" class="TwigSwiftMailer">
<factory service="propeo_user.mailer.factory" method="createTwigSwiftMailer" />
<argument type="service" id="acme.mailer_name_provider" />
<argument type="service" id="router" />
<argument type="service" id="twig" />
<argument type="collection">
<argument key="template" type="collection">
<argument key="confirmation">%fos_user.registration.confirmation.template%</argument>
<argument key="resetting">%fos_user.resetting.email.template%</argument>
</argument>
</argument>
</service>
а также заводской класс:
# Acme/UserBundle/Service/TwigSwiftMailerFactory
class TwigSwiftMailerFactory extends ContainerAware
{
private function getContainer()
{
if(!($this->container instanceof ContainerInterface)) {
throw new \RuntimeException('Container is missing');
}
return $this->container;
}
public function createTwigSwiftMailer(MailerNameProvider $mailerNameProvider, UrlGeneratorInterface $router, \Twig_Environment $twig, array $parameters)
{
$container = $this->getContainer();
$name = $mailerNameProvider->getMailerName(); // returns mailer name, e.g. mailer_en
$mailer = $container->get(
sprintf('swiftmailer.mailer.%s', $name ? $name : 'default')
);
$parameters['from_email']['confirmation'] =
$parameters['from_email']['resetting'] =
$container->getParameter(
sprintf('swiftmailer.mailer.%s.sender_address', $name ? $name : 'default')
)
;
return new TwigSwiftMailer($mailer, $router, $twig, $parameters);
}
}