Symfony 4 : Inject your env’s configuration in your service — second pattern

available since 3.4 but the last version has got so powerfull DX

In my last article, available here, I’ve presented how to inject your env’s configuration with the powerfull ParameterBagInterface feature.

After the publication, I was commented to tell me that this method was too “brutal” in my context since I knew in advance the parameter that I wanted to use. So no need to inject all the container of resources. Thank you so much for this feedbacks. Thanks to you I went to discover new things.

So I went through the various articles and the official doc to find a better solution. I think i’ve found this here : https://symfony.com/blog/new-in-symfony-3-4-local-service-binding

Let’s fucking go to try this.

To test this another pattern, I took my old code.

A very simple DownloadHelper
The linked interface
One random entity that implements the interface so downloadable
my .env configuration

To finish, my services.yaml with new binding. I’ve rename my binding $path to $downloadPath because we’ll see that now this parameter is resolved automatically so “path” is maybe too vagueness.

services.yaml with parameter binding. Compared on my last version, no need to define parameters node

So, if I rely on the documentation it seems okay.

I can test it with previous test defined. As a reminder with some adjustments because now I don’t use ParameterBagInterface.

One test for this downloadHelper
Ouput command

However if we think a little, in this test I can’t validate that my injection works since I instantiate here my DownloadHelper with a value for the variable $downloadPath.

So, this is not relevant. There is another way I like to validate the immediate errors: launch the cache (and in particular the corresponding warmup).

output cache:clear command

Ok, it’s seems good. But as I repeat often, no satisfactory green under red prior. “Beware of the false positive” (wink my favorite lead technique ;))

So, I’ll try to modify my parameter’s name in my DownloadHelper construct. In theory, if the name is not the same, it will not be resolved.

I modified the parameter’s constructor name

My test is always green but the cache:clear is red. YES ! In fact, it is normal that my test does not crash because I do not test the injection of dependencies but only the path’s getter.

cache:clear when I modified my parameter’s name

Ok, so when my parameter’s name is the same as the one defined in my services.yaml file, I do not have an error but if I modified it I have one. “ 
It smells good”. But I’m a skeptic so to be sure I have to go further and check the behavior of my helper.

For that, I quickly created a command. (I could have used the incredible maker component .. )

My command to test helper’s behavior.
output command

AWESOME !

Last test, I’m just going to check that by modifying the binding in services.yaml, my command does not work anymore.

I changed the binding. My command ?
Yes ! Nice error :)

Oh nice. In addition to warn me if a bind is not defined, if a bind is not expected I have an error too. (ping notice error in Core’s PHP when you use one undefined variable :()

To conclude, if you need to use one env’s configuration, you can bind it in your services.yaml et inject it in your service automatically with the powerfull autowiring/autoconfigure feature in Symfony’s dependency injection.

Of course, if you need you can define one specific binding for your service in your configurations like this.

In this case, only for your DownloadHelper you have overwritten your $pathDownload
.env file with new configuration
Specific binding for this service

Please becareful when you define your bind’s naming. The naming is always so important but here it’s more sensitive. Your binds are shared so you have to give them meaningful names.

Again, thank you for your previous feedback because this solution is even simpler (and if it is cleaner technically, the world is happy)