Search code examples
phpsymfonydependency-injection

Symfony DI pass new instance with arguments to constructor without creating bazillion service aliases?


I have a super useful class B that have a single argument constructor.

I will use this class bazillion times in definition of other services in Symfony DI.

How can I avoid duplicating B service definition N times for the sake of creating aliases?

pseudo-code I would love to use:

A:
 aruguments:
  $someList:
   - B 'b1'
   - B 'b2'
   - B 'b3'
C:
 arguments:
  $someOtherList:
   - B 'b4'
   - B 'b999'
   - ...
D:
...

Why do I have so many B's ? Because there is repeating behavior through my algorithm and B with single argument through constructor is enough to never repeat that behavior.

Why can't I roll B into A or C? A and C are collection/container style classes and I will have many of those. Would create explosion in classes created for each combination.

What's the code I would write without DI?

new A([
 new B('b1'),
 new B('b2'),
 new B('b3'),
]);

...

new C([
 new B('b4'),
 new B('b99'),
 ...
]);

...

new D([
 ...

So, how do I write equivalent symfony service definitions?


Solution

  • Edit after a year with above code:

    Using Symfony DI for configuring those classes was a mistake. First clue is that all of the classes that will be declared as anonymous services will only be used by their top level services. Second clue is that their configuration is quite rigid throughout the lifetime of this application.

    Simpler solution would be to instantiate them all inside one or just a few Factories, and register top level services with those Factories.

    Original answer:

    Solution I found is inline service definitions!

    You can do that by prepending !service to an object containing necessary data:

    A:
     aruguments:
      $someList:
       - !service { class:B, arguments: ['b1']}
       - !service { class:B, arguments: ['b2']}
       - !service { class:B, arguments: ['b3']}
    C:
     arguments:
      $someOtherList:
       - !service { class:B, arguments: ['b4']}
       - !service { class:B, arguments: ['b999']}
       - ...
    D: