Do you Autowire Services in Symfony? You can Autowire Parameters Too
Why?
The AutoBindParameter package is now deprecated. Parameter autowiring proven to be magical and cofusing approach.
Use constant parameters instead.
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? |
---|---|
|
|
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.
Or...?
(Place your crazy ideas below ↓)
Have you find this post useful? Do you want more?
Follow me on Twitter, RSS or support me on GitHub Sponsors.