Symfony2:依赖注入依赖于请求
Symfony2: Dependency injection reliant on request
序言
我的 Symfony2 应用程序将从多个 TLD 访问。根据 TLD,我想使用不同的 swiftmailer 邮件程序。然而,尽管尝试了多种方法(服务工厂、编译器传递、DI 扩展、"dynamic alias"),我还是未能动态注入正确的邮件程序。
这导致了一个基本的认识:依赖被注入 before 容器被编译,请求可用 after 容器被编译.因此没有办法使依赖注入依赖于请求(因此所有上述方法都失败了)。
问题
有人告诉我永远不要提取依赖项,而要始终注入它们。
进一步说明:
我有
- three swiftmailers:mailer_en、mailer_de、mailer_ie 和
- 三个域:domain.co.uk、domain.de 和 domain.ie
并想将正确的 swiftmailer 注入 custom mailer service for FOSUserBundle(或任何其他需要 swiftmailer 的服务)。
问题
如果在请求可用之前我不知道如何注入正确的依赖项?
我有两个想法,但不确定它们是否合适:
- 我应该注射某种 "Mailer Provider" 吗?仍然有点依赖关系,不是吗?
- 我可以使用某种代理 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);
}
}
序言
我的 Symfony2 应用程序将从多个 TLD 访问。根据 TLD,我想使用不同的 swiftmailer 邮件程序。然而,尽管尝试了多种方法(服务工厂、编译器传递、DI 扩展、"dynamic alias"),我还是未能动态注入正确的邮件程序。
这导致了一个基本的认识:依赖被注入 before 容器被编译,请求可用 after 容器被编译.因此没有办法使依赖注入依赖于请求(因此所有上述方法都失败了)。
问题
有人告诉我永远不要提取依赖项,而要始终注入它们。
进一步说明:
我有
- three swiftmailers:mailer_en、mailer_de、mailer_ie 和
- 三个域:domain.co.uk、domain.de 和 domain.ie
并想将正确的 swiftmailer 注入 custom mailer service for FOSUserBundle(或任何其他需要 swiftmailer 的服务)。
问题
如果在请求可用之前我不知道如何注入正确的依赖项?
我有两个想法,但不确定它们是否合适:
- 我应该注射某种 "Mailer Provider" 吗?仍然有点依赖关系,不是吗?
- 我可以使用某种代理 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);
}
}