Ver índice de contenidos del libro

16.7. Inyectando servicios opcionales

En ocasiones, algún servicio puede tener dependencias opcionales, lo cual significa que esas dependencias no son obligatorias para que el servicio funcione correctamente. En el ejemplo anterior, el servicio my_mailer debe existir, ya que si no, se lanzará una excepción. Modificando la definición del servicio newsletter_manager, puedes hacer que esta dependencia sea opcional. De esta forma, el contenedor inyectará el servicio si existe y no hará nada si el servicio inyectado no existe:

# src/Acme/HelloBundle/Resources/config/services.yml
parameters:
    # ...

services:
    newsletter_manager:
        class:     %newsletter_manager.class%
        arguments: ["@?my_mailer"]
<!-- src/Acme/HelloBundle/Resources/config/services.xml -->
 
<services>
    <service id="my_mailer" ...>
      <!-- ... -->
    </service>
    <service id="newsletter_manager" class="%newsletter_manager.class%">
        <argument type="service" id="my_mailer" on-invalid="ignore" />
    </service>
</services>
// src/Acme/HelloBundle/Resources/config/services.php
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerInterface;
 
// ...
$container->setParameter(
    'newsletter_manager.class',
    'Acme\HelloBundle\Newsletter\NewsletterManager'
);
 
$container->setDefinition('my_mailer', ...);
$container->setDefinition('newsletter_manager', new Definition(
    '%newsletter_manager.class%',
    array(
        new Reference(
            'my_mailer',
            ContainerInterface::IGNORE_ON_INVALID_REFERENCE
        )
    )
));

En YAML, la sintaxis especial @? le dice al contenedor de servicios que la dependencia es opcional. Alternativamente, puedes preparar el código de la clase NewsletterManager para que la dependencia sea opcional:

public function __construct(Mailer $mailer = null)
{
    // ...
}