Symfony2:依赖注入依赖于请求

Symfony2: Dependency injection reliant on request

序言

我的 Symfony2 应用程序将从多个 TLD 访问。根据 TLD,我想使用不同的 swiftmailer 邮件程序。然而,尽管尝试了多种方法(服务工厂、编译器传递、DI 扩展、"dynamic alias"),我还是未能动态注入正确的邮件程序。

这导致了一个基本的认识:依赖被注入 before 容器被编译,请求可用 after 容器被编译.因此没有办法使依赖注入依赖于请求(因此所有上述方法都失败了)。

问题

有人告诉我永远不要提取依赖项,而要始终注入它们。

进一步说明:

我有

并想将正确的 swiftmailer 注入 custom mailer service for FOSUserBundle(或任何其他需要 swiftmailer 的服务)。

问题

如果在请求可用之前我不知道如何注入正确的依赖项?

我有两个想法,但不确定它们是否合适:

  1. 我应该注射某种 "Mailer Provider" 吗?仍然有点依赖关系,不是吗?
  2. 我可以使用某种代理 class,将交互转发给正确的电子邮件吗?

还是我完全走错了路线?

正在注入请求 is covered in the documentation. That being said, I think you'll get the most bang for the buck by using a factory

为了将来参考,这里是 的实现:

Custom mailer for 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>

以及工厂class:

# 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);
    }
}