Home » Php » php – Symfony Dependency Injection inject new instance of class

php – Symfony Dependency Injection inject new instance of class

Posted by: admin July 12, 2020 Leave a comment

Questions:

I’m using symfony/dependency-injection component (note: not using the full stack framework)

When registering a new service i want to inject in the constructor a new instance of a class. Example:

$container->register('session', 'Vendor\Core\Session')
    ->addArgument(new PhpBridgeSessionStorage());

The example works very well but what if I want to use yml files for defining this service? Something like:

services:
  session:
    class: Vendor\Core\Session
    arguments: [ new Class\To\Inject ]

Am I forced to define Class\To\Inject as a new service? or create a Service factory?

How to&Answers:

Scopes have been deprecated since 2.8. Use shared: false instead.

http://symfony.com/doc/current/cookbook/service_container/shared.html

services:
  session:
    class: Vendor\Core\Session
    arguments: [ "@inject.me" ]

  inject.me:
    class: Class\To\Inject
    shared: false

Answer:

I now that this question is pretty old but here is a trick that you could use to avoid define every simple class as service defining a “factory class” service that receive the class to create as argument and after through “expression language” inject as argument:

<?php

final class ClassFactory
{
   public static function create($class, array $arguments = [])
   {
     return new $class($arguments);
   }
}
  • create the new service

    app.class_factory:
    class: ClassFactory

  • after inject the new classes like that:

    arguments: [‘@=service(“app.class_factory”).create(“Monolog\Logger”)’]

For Symfony >=2.8 you can take a look to the “auto-wiring” feature also -> http://symfony.com/blog/new-in-symfony-2-8-service-auto-wiring

Answer:

Yes, all classes you inject should be services. You can give them a scope of prototype to create a new instance each time it’s requested.

For more information see: http://symfony.com/doc/current/cookbook/service_container/scopes.html

Answer:

I have been looking for this answer myself for a library which just needs to create some value objects (services) for other services, and I felt like all these services in YAML (with long unique names) were polluting the service configuration compared to defining the value objects without a service name in PHP.

In regular applications this is actually not a problem when using a current Symfony version (3.4+) where all services are private by default, as the service container will notice itself if a private service is only used once and then inline it (so the name will not be used), resulting in exactly the same service container code as when you define the service without a name in PHP.

So as long as you declare all the services as private (or use the defaults in Symfony 3.4+) they will be optimized accordingly (and removed if not used).