DependencyInjection

1.Basic Usage

class Mailer
{
    private $transport;

    public function __construct()
    {
        $this->transport = 'sendmail';
    }

    // ...
}

2.register this in the container as a service

use Symfony\Component\DependencyInjection\ContainerBuilder;

$containerBuilder = new ContainerBuilder();
$containerBuilder->register('mailer', 'Mailer');

3.allow the container to set the transport used

class Mailer
{
    private $transport;

    public function __construct($transport)
    {
        $this->transport = $transport;
    }
    // ...
}

4.Then you can set the choice of transport in the container

use Symfony\Component\DependencyInjection\ContainerBuilder;

$containerBuilder = new ContainerBuilder();
$containerBuilder
    ->register('mailer', 'Mailer')
    ->addArgument('sendmail');

5.Which mail transport you have chosen may be something other services need to know about

use Symfony\Component\DependencyInjection\ContainerBuilder;

$containerBuilder = new ContainerBuilder();
$containerBuilder->setParameter('mailer.transport', 'sendmail');
$containerBuilder
    ->register('mailer', 'Mailer')
    ->addArgument('%mailer.transport%');

6.Now that the mailer service is in the container you can inject it as a dependency of other classes

class NewsletterManager
{
    private $mailer;

    public function __construct(\Mailer $mailer)
    {
        $this->mailer = $mailer;
    }

    // ...
}

7.Use the Reference class to tell the container to inject the mailer service when it initializes the newsletter manager

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

$containerBuilder = new ContainerBuilder();

$containerBuilder->setParameter('mailer.transport', 'sendmail');
$containerBuilder
    ->register('mailer', 'Mailer')
    ->addArgument('%mailer.transport%');

$containerBuilder
    ->register('newsletter_manager', 'NewsletterManager')
    ->addArgument(new Reference('mailer'));

8.If the NewsletterManager did not require the Mailer and injecting it was only optional then you could use setter injection instead

class NewsletterManager
{
    private $mailer;

    public function setMailer(\Mailer $mailer)
    {
        $this->mailer = $mailer;
    }

    // ...
}

9. you can now choose not to inject a Mailer into the NewsletterManager. If you do want to though then the container can call the setter method

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

$containerBuilder = new ContainerBuilder();

$containerBuilder->setParameter('mailer.transport', 'sendmail');
$containerBuilder
    ->register('mailer', 'Mailer')
    ->addArgument('%mailer.transport%');

$containerBuilder
    ->register('newsletter_manager', 'NewsletterManager')
    ->addMethodCall('setMailer', [new Reference('mailer')]);

10.Avoiding your Code Becoming Dependent on the Container

11.Setting up the Container with Configuration Files

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;

$containerBuilder = new ContainerBuilder();
$loader = new XmlFileLoader($containerBuilder, new FileLocator(__DIR__));
$loader->load('services.xml');