Movatterモバイル変換


[0]ホーム

URL:


Skip to content
Version:

The DependencyInjection Component

Edit this page

The DependencyInjection component implements aPSR-11 compatible servicecontainer that allows you to standardize and centralize the way objects areconstructed in your application.

For an introduction to Dependency Injection and service containers seeService Container.

Installation

1
$composer require symfony/dependency-injection

Note

If you install this component outside of a Symfony application, you mustrequire thevendor/autoload.php file in your code to enable the classautoloading mechanism provided by Composer. Readthis article for more details.

Basic Usage

See also

This article explains how to use the DependencyInjection features as anindependent component in any PHP application. Read theService Containerarticle to learn about how to use it in Symfony applications.

You might have a class like the followingMailer thatyou want to make available as a service:

1234567891011
classMailer{privatestring$transport;publicfunction__construct(){$this->transport ='sendmail';    }// ...}

You can register this in the container as a service:

1234
useSymfony\Component\DependencyInjection\ContainerBuilder;$container =newContainerBuilder();$container->register('mailer','Mailer');

An improvement to the class to make it more flexible would be to allowthe container to set thetransport used. If you change the classso this is passed into the constructor:

123456789
classMailer{publicfunction__construct(privatestring$transport,    ){    }// ...}

Then you can set the choice of transport in the container:

123456
useSymfony\Component\DependencyInjection\ContainerBuilder;$container =newContainerBuilder();$container    ->register('mailer','Mailer')    ->addArgument('sendmail');

This class is now much more flexible as you have separated the choice oftransport out of the implementation and into the container.

Which mail transport you have chosen may be something other services needto know about. You can avoid having to change it in multiple places by makingit a parameter in the container and then referring to this parameter fortheMailer service's constructor argument:

1234567
useSymfony\Component\DependencyInjection\ContainerBuilder;$container =newContainerBuilder();$container->setParameter('mailer.transport','sendmail');$container    ->register('mailer','Mailer')    ->addArgument('%mailer.transport%');

Now that themailer service is in the container you can inject it asa dependency of other classes. If you have aNewsletterManager classlike this:

123456789
classNewsletterManager{publicfunction__construct(private \Mailer$mailer,    ){    }// ...}

When defining thenewsletter_manager service, themailer service doesnot exist yet. Use theReference class to tell the container to inject themailer service when it initializes the newsletter manager:

12345678910111213
useSymfony\Component\DependencyInjection\ContainerBuilder;useSymfony\Component\DependencyInjection\Reference;$container =newContainerBuilder();$container->setParameter('mailer.transport','sendmail');$container    ->register('mailer','Mailer')    ->addArgument('%mailer.transport%');$container    ->register('newsletter_manager','NewsletterManager')    ->addArgument(newReference('mailer'));

If theNewsletterManager did not require theMailer and injectingit was only optional then you could use setter injection instead:

1234567891011
classNewsletterManager{private \Mailer$mailer;publicfunctionsetMailer(\Mailer$mailer):void{$this->mailer =$mailer;    }// ...}

You can now choose not to inject aMailer into theNewsletterManager.If you do want to though then the container can call the setter method:

12345678910111213
useSymfony\Component\DependencyInjection\ContainerBuilder;useSymfony\Component\DependencyInjection\Reference;$container =newContainerBuilder();$container->setParameter('mailer.transport','sendmail');$container    ->register('mailer','Mailer')    ->addArgument('%mailer.transport%');$container    ->register('newsletter_manager','NewsletterManager')    ->addMethodCall('setMailer', [newReference('mailer')]);

You could then get yournewsletter_manager service from the containerlike this:

1234567
useSymfony\Component\DependencyInjection\ContainerBuilder;$container =newContainerBuilder();// ...$newsletterManager =$container->get('newsletter_manager');

Getting Services That Don't Exist

By default, when you try to get a service that doesn't exist, you see an exception.You can override this behavior as follows:

123456789
useSymfony\Component\DependencyInjection\ContainerBuilder;useSymfony\Component\DependencyInjection\ContainerInterface;$containerBuilder =newContainerBuilder();// ...// the second argument is optional and defines what to do when the service doesn't exist$newsletterManager =$containerBuilder->get('newsletter_manager', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);

These are all the possible behaviors:

  • ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE: throws an exceptionat compile time (this is thedefault behavior);
  • ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE: throws anexception at runtime, when trying to access the missing service;
  • ContainerInterface::NULL_ON_INVALID_REFERENCE: returnsnull;
  • ContainerInterface::IGNORE_ON_INVALID_REFERENCE: ignores the wrappingcommand asking for the reference (for instance, ignore a setter if the servicedoes not exist);
  • ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE: ignores/returnsnull for uninitialized services or invalid references.

Avoiding your Code Becoming Dependent on the Container

Whilst you can retrieve services from the container directly it is bestto minimize this. For example, in theNewsletterManager you injectedthemailer service in rather than asking for it from the container.You could have injected the container in and retrieved themailer servicefrom it but it would then be tied to this particular container making itdifficult to reuse the class elsewhere.

You will need to get a service from the container at some point but thisshould be as few times as possible at the entry point to your application.

Setting up the Container with Configuration Files

As well as setting up the services using PHP as above you can also useconfiguration files. This allows you to use XML or YAML to write the definitionsfor the services rather than using PHP to define the services as in theabove examples. In anything but the smallest applications it makes senseto organize the service definitions by moving them into one or more configurationfiles. To do this you also need to installthe Config component.

Loading an XML config file:

1234567
useSymfony\Component\Config\FileLocator;useSymfony\Component\DependencyInjection\ContainerBuilder;useSymfony\Component\DependencyInjection\Loader\XmlFileLoader;$container =newContainerBuilder();$loader =newXmlFileLoader($container,newFileLocator(__DIR__));$loader->load('services.xml');

Loading a YAML config file:

1234567
useSymfony\Component\Config\FileLocator;useSymfony\Component\DependencyInjection\ContainerBuilder;useSymfony\Component\DependencyInjection\Loader\YamlFileLoader;$container =newContainerBuilder();$loader =newYamlFileLoader($container,newFileLocator(__DIR__));$loader->load('services.yaml');

Note

If you want to load YAML config files then you will also need to installthe Yaml component.

Tip

If your application uses unconventional file extensions (for example, yourXML files have a.config extension) you can pass the file type as thesecond optional parameter of theload() method:

12
// ...$loader->load('services.config','xml');

If youdo want to use PHP to create the services then you can move thisinto a separate config file and load it in a similar way:

1234567
useSymfony\Component\Config\FileLocator;useSymfony\Component\DependencyInjection\ContainerBuilder;useSymfony\Component\DependencyInjection\Loader\PhpFileLoader;$container =newContainerBuilder();$loader =newPhpFileLoader($container,newFileLocator(__DIR__));$loader->load('services.php');

You can now set up thenewsletter_manager andmailer services usingconfig files:

123456789101112
parameters:# ...mailer.transport:sendmailservices:mailer:class:Mailerarguments:['%mailer.transport%']newsletter_manager:class:NewsletterManagercalls:-[setMailer,['@mailer']]
1234567891011121314151617181920212223
<?xml version="1.0" encoding="UTF-8" ?><containerxmlns="http://symfony.com/schema/dic/services"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://symfony.com/schema/dic/services        https://symfony.com/schema/dic/services/services-1.0.xsd"><parameters><!-- ... --><parameterkey="mailer.transport">sendmail</parameter></parameters><services><serviceid="mailer"class="Mailer"><argument>%mailer.transport%</argument></service><serviceid="newsletter_manager"class="NewsletterManager"><callmethod="setMailer"><argumenttype="service"id="mailer"/></call></service></services></container>
123456789101112131415161718192021
namespaceSymfony\Component\DependencyInjection\Loader\Configurator;returnstaticfunction(ContainerConfigurator$container):void{$container->parameters()// ...        ->set('mailer.transport','sendmail')    ;$services =$container->services();$services->set('mailer','Mailer')        ->args(['%mailer.transport%'])    ;$services->set('mailer','Mailer')        ->args([param('mailer.transport')])    ;$services->set('newsletter_manager','NewsletterManager')        ->call('setMailer', [service('mailer')])    ;};

Learn More

This work, including the code samples, is licensed under aCreative Commons BY-SA 3.0 license.
TOC
    Version

    Symfony 7.3backers


    [8]ページ先頭

    ©2009-2025 Movatter.jp