Do you Autowire Services in Symfony? You can Autowire Parameters Too

4 min

Mon, Nov 5, 2018

X comments

Edit Post

I love how Symfony caught up late autowiring integration in since Symfony 2.8. Then set a trend in Symfony 3.3 with service autoregistration.



That opens new possibilities to almost config-less registration, doesn't it?

Do you still have these old-school Symfony 2.7- configs?

# services.yml services: first_service: class: 'OpenProject\FirstClass' second_service: class: 'OpenProject\SecondClass' arguments: - '@first_service'

You have to register every service manually and set service arguments manually.

Honestly, I envy you. I can't imagine more wet PHP dream than refactoring to autowiring.





Are running on a newer Symfony? You'll be more familiar with this syntax:

# services.yml services: OpenProject\FirstClass: ~ OpenProject\SecondClass: arguments: - '@OpenProject\FirstClass'

...or even...

# services.yml services: _defaults: autowire: true OpenProject\FirstClass: ~ OpenProject\SecondClass: ~

...or even on the final one - autodiscovery:

# services.yml services: _defaults: autowire: true OpenProject\: resource: "../src"

This allows you to forget, that you actually have any config with services.

Why? Because creating and using new service = creating a PHP class. No YAML, no XML, no whatever memory-locking configuration.





Programmers used DI containers, config was getting into the shape of Miss World, autowiring and autodiscovery became status-quo and life was good.

Suddenly...

...You Want to Use Parameters

No problem! Since you already know the clean-way, you'll use constructor:

<?php namespace OpenProject; class FirstClass { public function __construct(string $apiKey) { // ... } }

And add parameter values to config:

parameters: api_key: "asdf"

How do we get those parameters in there?

services: _defaults: autowire: true OpenProject\: resource: "../src" + + OpenProject\FirstClass: + arguments: + - "%api_key%"

It's that simple! Just kidding.

Symfony guys realized this needs to follow innovations as service registration did.

services: _defaults: autowire: true + bind: + $apiKey: "%api_key%" OpenProject\: resource: "../src"

Not bad, at least compared to the previous solution.

New Service? New Parameter? create a PHP class

require it in the constructor create a parameter

require it in the constructor

bind it in config

bind it in every config where it is required by service

also, remove it from every config where it's not used anymore - otherwise you'll get nice Symfony exception

It's that simple! Just kidding, again.

Autowired Parameters in Symfony

If services are autowired by unique type,

parameters can be autowired by unique name.

You don't need this:

services: _defaults: autowire: true - bind: - $apiKey: "%api_key%" OpenProject\: resource: "../src"

All you need is... love... and to:

create a parameter

parameters: api_key: "asdf"

require it in the constructor

<?php namespace OpenProject; class FirstClass { public function __construct(string $apiKey) { // ... } }

That's all folks!





Convention over Configuration

If you can shave off 2 almost identical approaches - element autowiring - to single 1, do it.

By respecting the naming %param% = $param your code is consistent with services,

where Type = $type and clean and easy to read.





I got bad news - this is not part of Symfony - yet. But neither was autowiring for 8 years until it was.

In the meantime, register Symplify\PackageBuilder\DependencyInjection\CompilerPass\AutoBindParametersCompilerPass .

You don't know how? See Symfony docs.





How Far Can We Push Autowiring Together?

What about array-typed autowiring?

<?php class SomeClass { /** * @param CollectedType[] $collectedClasses */ public function __construct(array $collectedClasses) { // ... } }

Done for Symfony 3.4+ and in Nette 3.0.





Maybe convention factory using create() method and it's @return Type or create(): Type ?

services: SomeFactory: ~ - SomeObject: - factory: ['@SomeFactory', 'create']

EDITED: Done for Symfony 3.4+





Or...?

(Place your crazy ideas below ↓)