Stephen Harris
Stephen Harris

Reputation: 1184

Pick interface implementation based on parameter in Symfony config

Lets suppose I have an interface ThingInterface and two implementations Thing and MockThing. Now assuming I am using dependency injection and I have programmed against ThingInterface then in symfony I can tell it which implementation to use, as follows:

services:
    ...
    ThingInterface: '@Thing'
    ...

Is it possible to pick and implementation to use based on a parameter? E.g:

parameters:
    useMock: 'true'

services:
    ...
    # ThingInterface maps to ThingMock or Thing based on useMock parameter
    ThingInterface: '@ThingMock'
    ...

I'm using symfony 3.4.

The context here is that I'll have a number of services, and I want to easily switch between an actual implementation and mocked version. I can do this individually for each service, but I was hoping I can do this through a parameter 'toggle'.

I found this which gives this example:

services:
    AppBundle\Mailer:
        arguments: ["@=container.hasParameter('some_param') ? parameter('some_param') : 'default_value'"]

But I have been unable to make it work for mapping interfaces to implementations:

parameters:
    useMock: 'true'

services:
    ...
    # ThingInterface maps to ThingMock or Thing based on useMock parameter
    ThingInterface: '@ThingMock'
    ThingInterface: ["@=container.getParameter('useMock') ? service('ThingMock') : service('Thing')"]
    ...

Upvotes: 1

Views: 1786

Answers (1)

jgmjgm
jgmjgm

Reputation: 4705

For some unknown reason, the shorthand of just setting a string to alias/remap to doesn't seem to evaluate at all with symfony.

You can try this:

Namespace\ClassA: ~
Namespace\ClassB: ~
Namespace\MyInterface:
    class: '%my_interface.class%'

However, you'll probably end up with two instances of the class (two services). Alias unfortunately doesn't seem to work, neither will import.

The only other options seem ugly and basically lose autowiring, IE, binding everywhere.

Unfortunately these are the only ways to do it as symfony doesn't support what you're asking for.

If you want to do that you have to implement that as a framework extension or use a different framework. There's a bunch of github issues and denied pull requests confirming this.

Upvotes: 2

Related Questions