如何令服务的参数/引用成为可选
有时,你的某个服务会有一个可选的依赖,这意味着该服务没有这个依赖时也能正常工作。前面例子中,app.mailer
服务是必须要存在的,否则会抛出异常。通过修改newsletter_manager
的服务定义,你可以令它对app.mailer
的引用变为可选。容器将在依赖存在时实施注入,否则什么也不做:
将错失的依赖设为null ¶
你可以使用null技巧,来显式指定服务定义中的参数为null,如果该服务不存在的话:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<!-- app/config/services.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="Http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="app.mailer">
<!-- ... -->
</service>
<service id="app.newsletter_manager" class="AppBundle\Newsletter\NewsletterManager">
<argument type="service" id="app.mailer" on-invalid="null" />
</service>
</services>
</container> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// app/config/services.php
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerInterface;
$container->setDefinition('app.mailer', ...);
$container->setDefinition('app.newsletter_manager', new Definition(
'AppBundle\Newsletter\NewsletterManager',
array(
new Reference(
'app.mailer',
ContainerInterface::NULL_ON_INVALID_REFERENCE
)
)
)); |
null配置技巧现已不被YAML驱动所支持
忽略错失的依赖 ¶
忽略错失依赖,在行为上与显式指定“null”是一样的,除了在方法调用中使用时,方法本身会被删除。
下述例子中,容器将以构造器方式注入一个服务到app.newsletter_manager
服务中,前提是该服务存在。若不存在,将移除构造方法:
1 2 3 4 5 |
# app/config/services.yml
services:
app.newsletter_manager:
class: AppBundle\Newsletter\NewsletterManager
arguments: ['@?app.mailer'] |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<!-- app/config/services.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="app.mailer">
<!-- ... -->
</service>
<service id="app.newsletter_manager" class="AppBundle\Newsletter\NewsletterManager">
<call method="setMailer">
<argument type="service" id="my_mailer" on-invalid="ignore"/>
</call>
</service>
</services>
</container> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// app/config/services.php
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerInterface;
$container->setDefinition('app.mailer', ...);
$container->setDefinition('app.newsletter_manager', new Definition(
'AppBundle\Newsletter\NewsletterManager'
))->addMethodCall('setMailer', array(
new Reference(
'my_mailer',
ContainerInterface::IGNORE_ON_INVALID_REFERENCE
),
)); |
YAML中特殊的@?
语法告诉服务容器这个依赖是可选的。当然, NewsletterManager
类必须也要重新修改为可选依赖:
1 2 3 4 |
public function __construct(Mailer $mailer = null)
{
// ...
} |