8

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?

spdionis
  • 307
  • 1
  • 4
  • 11

4 Answers4

7

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
martin
  • 93,354
  • 25
  • 191
  • 226
2

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

Félix
  • 41
  • 3
0

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

Wouter J
  • 41,455
  • 15
  • 107
  • 112
  • 1
    This would mean polluting the configuration file with a lot of use-once services that have no dependencies and that shouldn't be used outside of the building of the container. I'd rather build this part of the container with PHP in this case. – spdionis Feb 20 '14 at 15:30
  • @spdionis If it shouldn't be used outside of the container, they should be marked as `public=false` (private). You have to put them into a container, that's how it works :) – Wouter J Feb 20 '14 at 16:47
  • 1
    I'm just scared of ending up with 100 services. – spdionis Feb 20 '14 at 17:23
0

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).

iquito
  • 2,388
  • 1
  • 18
  • 26