8

I try to figure out how to manually inject arguments to DefaultController (without autowiring). And there are two ways I have found to achieve this.

I can use arguments:

services:
    _defaults:
        autowire: false
        autoconfigure: true
        public: true

    App\Service\SomeService: ~

    App\Controller\DefaultController:
        arguments:                                    #!
            $service: '@App\Service\SomeService'
            $scalar: 22

And along with this, I can use bind key:

services:
    _defaults:
        autowire: false
        autoconfigure: true
        public: true

    App\Service\SomeService: ~

    App\Controller\DefaultController:
        bind:                                         #!
            $service: '@App\Service\SomeService'
            $scalar: 22

My controller:

class DefaultController extends Controller
{
    public function __construct($service, $scalar)
    {
        var_dump(get_class($service), $scalar);
    }
...

Both options produce the same output:

string(23) "App\Service\SomeService" int(22)

So what is the difference between this two configuration keys arguments and bind, do they do the exact same thing ?

Alexey Chuhrov
  • 1,787
  • 12
  • 25

3 Answers3

6

bind is usually used in the _defaults section to replace any matching argument name in the services that are defined by that file.

So, taking the variables names from second example, and putting them into the more usual _defaults: stanza

_defaults:
    # autowire / autoconfig, etc
    bind:                                         #!
        $service: '@App\Service\SomeService'
        $scalar: 22

Any services that had those variable names would be replaced (unless locally overridden) with the service, or scalar value (22).

Alister Bulman
  • 34,482
  • 9
  • 71
  • 110
  • 2
    I thought about that too, but Im not sure. Reading the docs, sometimes I find examples with [`bind`](https://symfony.com/doc/current/controller.html#fetching-services) (here it is not in the `_defaults` section) and sometimes with `arguments`. I find it inconsistent. If `arguments` can not be used in `_defaults` and `bind` can be used everywhere why then do we need `arguments` at all – Alexey Chuhrov Apr 17 '18 at 11:47
  • 4
    According to the note in your bind link, the bound variables will be passed into any of your actions as well as the constructor. So I think using bind for a given service is a special case as only controllers support action injection. I have not tied it but I'm also guessing that having a bind for a specific service will allow overriding a _default bind. Harry Potter would be so proud. – Cerad Apr 17 '18 at 12:32
2

bind is used for a more global approach, as explained by Alister Bulman. But when used on a class definition, bind and arguments are more or less the same.

The only difference I see is that arguments is more flexible and accepts an array:

App\Controller\DefaultController:
    arguments:
        - '@App\Service\SomeService'
        - 22

arguments also has priority over bind.

I guess the documentation is inconsistent because bind is relatively new.

fxbt
  • 2,556
  • 19
  • 19
1

one more thing to add - bind is for "bind arguments by name or type" and can also be used when loading multiple services at once - https://symfony.com/doc/current/service_container.html#binding-arguments-by-name-or-type .

edit: you can use arguments in multiple services definition as well, but it "force injects" those arguments to all instantiated services, ie. all arguments must be accepted in all services, while bind injects on demand.

Smoky McPot
  • 59
  • 1
  • 6
  • FileLoaderLoadException: The configuration key "arguments" cannot be used to define a default value. Allowed keys are "public", "tags", "autowire", "autoconfigure", "bind". – Maxim Mandrik Nov 26 '19 at 08:49
  • perhaps they changed the behavior in latest version. if you need define arguments in generic service definition, use bind. – Smoky McPot Nov 27 '19 at 13:00