Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony AutoWire multiple services same class

i am in the process of upgrading a large application to 4.2

and the $this->get(".....") from inside the controller is deprecated and one should use AutoWire instead.

i am running into the problem that i have 2 services, which are in fact from the same class (just diffrent constructor args).

services.yml

services:
  service.a:
    class: Namespace\MyClass
    arguments: [ "argument1" ]

  service.b:
    class: Namespace\MyClass
    arguments: [ "argument2" ]

controller:

public function demoAction() {
  $serviceA = $this->get("service.a");
  $serviceB = $this->get("service.b");
}

and the problematic result:

public function demoAction(MyClass $serviceA, MyClass $serviceB) {
}

we can use alias to service definitions like:

MyClass: '@service.a'

but i cannot use a virtual/fake class like (without an existing one):

MyPseudClass: '@service.b'

how do you handle cases like this in autowire mode?

i could create "pseudo" classes, that extend from the base, just to get different classnames, but that feels weird.

like image 769
Helmut Januschka Avatar asked Nov 30 '18 10:11

Helmut Januschka


2 Answers

Starting with 4.2, you can define named autowiring aliases. That should work:

services:
    Namespace\MyClass $serviceA: '@service.a'
    Namespace\MyClass $serviceB: '@service.b'

With Symfony 3.4 and 4.1, you can use bindings instead - but that's less specific as that doesn't take the type into account:

services:
    _defaults:
        bind:
            $serviceA: '@service.a'
            $serviceB: '@service.b'
like image 120
Nicolas Grekas Avatar answered Nov 05 '22 05:11

Nicolas Grekas


Another options is to implement the Factory Pattern. This pattern will enable you to create a service based on the arguments provided.

# services.yml
service.a:
    class: App\MyClass
    factory: 'App\Factory\StaticMyClassFactory:createMyClass'
    arguments:
        - ['argument1']

service.b:
    class: App\MyClass
    factory: 'App\Factory\StaticMyClassFactory:createMyClass'
    arguments:
        - ['argument2']

And your StaticMyClassFactory would look like this

class StaticMyClassFactory
{  
    public static function createMyClass($argument)
    {
        // Return your class based on the argument passed
        $myClass = new MyClass($argument);

        return $myClass;
    }
}
like image 29
Leander Avatar answered Nov 05 '22 05:11

Leander