Defining Services Dependencies Automatically (Autowiring)

Autowiring allows you to manage services in the container with minimal configuration.
It reads the type-hints on your constructor (or other methods) and automatically
passes you the correct services. Symfony's autowiring is designed to be predictable:
if it is not absolutely clear which dependency should be passed, you'll see an
actionable exception.

Tip

Thanks to Symfony's compiled container, there is no runtime overhead for using
autowiring.

namespaceAppBundle\Service;useAppBundle\Util\Rot13Transformer;classTwitterClient{private$transformer;publicfunction__construct(Rot13Transformer$transformer){$this->transformer=$transformer;}publicfunctiontweet($user,$key,$status){$transformedStatus=$this->transformer->transform($status);// ... connect to Twitter and send the encoded status}}

If you're using the default services.yml configuration,
both classes are automatically registered as services and configured to be autowired.
This means you can use them immediately without any configuration.

However, to understand autowiring better, the following examples explicitly configure
both services. Also, to keep things simple, configure TwitterClient to be a
public service:

YAML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

services:_defaults:autowire:trueautoconfigure:truepublic:false# ...AppBundle\Service\TwitterClient:# redundant thanks to _defaults, but value is overridable on each serviceautowire:true# not required, will help in our examplepublic:trueAppBundle\Util\Rot13Transformer:autowire:true

useAppBundle\Service\TwitterClient;useAppBundle\Util\Rot13Transformer;// ...// the autowire method is new in Symfony 3.3// in earlier versions, use register() and then call setAutowired(true)$container->autowire(TwitterClient::class)->setPublic(true);$container->autowire(Rot13Transformer::class)->setPublic(false);

Now, you can use the TwitterClient service immediately in a controller:

The autowiring system looks for a service whose id exactly matches the type-hint:
so AppBundle\Util\Rot13Transformer. In this case, that exists! When you configured
the Rot13Transformer service, you used its fully-qualified class name as its
id. Autowiring isn't magic: it simply looks for a service whose id matches the type-hint.
If you load services automatically,
each service's id is its class name. This is the main way to control autowiring.

If there is not a service whose id exactly matches the type, then:

If there are 0 services in the container that have the type, then:

If the type is a concrete class, then a new, private, autowired service is
auto-registered in the container and used for the argument.

If there is exactly 1 service in the container that has the type, then:

(deprecated) This service is used for the argument. In Symfony 4.0, this
will be removed. The proper solution is to create an alias
from the type to the service id so that normal autowiring works.

If there are 2 or more services in the container that have the type, then:

The main way to configure autowiring is to create a service whose id exactly matches
its class. In the previous example, the service's id is AppBundle\Util\Rot13Transformer,
which allows us to autowire this type automatically.

This can also be accomplished using an alias. Suppose that
for some reason, the id of the service was instead app.rot13.transformer. In
this case, any arguments type-hinted with the class name (AppBundle\Util\Rot13Transformer)
can no longer be autowired (actually, it will work now, but not in Symfony 4.0).

No problem! To fix this, you can create a service whose id matches the class by
adding a service alias:

YAML

1
2
3
4
5
6
7
8
9
10
11
12

services:# ...# the id is not a class, so it won't be used for autowiringapp.rot13.transformer:class:AppBundle\Util\Rot13Transformer# ...# but this fixes it!# the ``app.rot13.transformer`` service will be injected when# an ``AppBundle\Util\Rot13Transformer`` type-hint is detectedAppBundle\Util\Rot13Transformer:'@app.rot13.transformer'

This creates a service "alias", whose id is AppBundle\Util\Rot13Transformer.
Thanks to this, autowiring sees this and uses it whenever the Rot13Transformer
class is type-hinted.

Tip

Aliases are used by the core bundles to allow services to be autowired. For
example, MonologBundle creates a service whose id is logger. But it also
adds an alias: Psr\Log\LoggerInterface that points to the logger service.
This is why arguments type-hinted with Psr\Log\LoggerInterface can be autowired.

But now, the type-hint (AppBundle\Util\TransformerInterface) no longer matches
the id of the service (AppBundle\Util\Rot13Transformer). This means that the
argument can no longer be autowired (actually, it
will work now, but not in Symfony 4.0).

services:# ...AppBundle\Util\Rot13Transformer:~# the ``AppBundle\Util\Rot13Transformer`` service will be injected when# an ``AppBundle\Util\TransformerInterface`` type-hint is detectedAppBundle\Util\TransformerInterface:'@AppBundle\Util\Rot13Transformer'

If you register this as a service, you now have two services that implement the
AppBundle\Util\TransformerInterface type. Symfony doesn't know which one should
be used for autowiring, so you need to choose one by creating an alias from the type
to the correct service id (see Working with Interfaces).

If you want Rot13Transformer to be the service that's used for autowiring, create
that alias:

YAML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

services:# ...AppBundle\Util\Rot13Transformer:~AppBundle\Util\UppercaseTransformer:~# the ``AppBundle\Util\Rot13Transformer`` service will be injected when# a ``AppBundle\Util\TransformerInterface`` type-hint is detectedAppBundle\Util\TransformerInterface:'@AppBundle\Util\Rot13Transformer'AppBundle\Service\TwitterClient:# the Rot13Transformer will be passed as the $transformer argumentautowire:true# If you wanted to choose the non-default service, wire it manually# arguments:# $transformer: '@AppBundle\Util\UppercaseTransformer'# ...

Thanks to the AppBundle\Util\TransformerInterface alias, any argument type-hinted
with this interface will be passed the AppBundle\Util\Rot13Transformer service.
But, you can also manually wire the other service by specifying the argument
under the arguments key.

New in version 3.3: Using FQCN aliases to fix autowiring ambiguities was introduced in Symfony
3.3. Prior to version 3.3, you needed to use the autowiring_types key.

When autowiring is enabled for a service, you can also configure the container
to call methods on your class when it's instantiated. For example, suppose you want
to inject the logger service, and decide to use setter-injection:

Autowiring will automatically call any method with the @required annotation
above it, autowiring each argument. If you need to manually wire some of the arguments
to a method, you can always explicitly configure the method call.

If you're using the Symfony Framework, you can also autowire arguments to your controller
action methods. This is a special case for autowiring, which exists for convenience.
See Fetching Services as Controller Arguments for more details.

Thanks to Symfony's compiled container, there is no performance penalty for using
autowiring. However, there is a small performance penalty in the dev environment,
as the container may be rebuilt more often as you modify classes. If rebuilding
your container is slow (possible on very large projects), you may not be able to
use autowiring.