On the web debug toolbar, I've got a little yellow icon that says 10 deprecation warnings. Rude! Let's click that!
These are all the ways that my code is using old, deprecated, uncool functionality. It's basically a list of stuff we need to update before upgrading to Symfony 4. And there are a few deprecations related to autowiring:
Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. You should rename or alias
security.user_password_encoder.genericto ... long class name...
The text in the deprecation may look slightly different for you: we updated it to be a bit more clear in Symfony 3.3.1.
This is saying that somewhere, we are type-hinting an argument with
Symfony\Component\Security\Core\Encoder\UserPasswordEncoder... but there is no
service in the container with that exact id. So, autowiring got busy: it looked
at every service and found exactly one -
that has this class. It passed this service to that argument.
And that is the part of autowiring that is deprecated. Looking across every service for a matching class or interface was a little more magic than we wanted in Symfony.
How do we fix this? Actually, there are two solutions!
Here's the first question: is there a different type-hint that we should be using instead for this service? Let's find out!
Head to your terminal. We already know about the
php bin/console debug:container
This gives us a big list of every public service in the container. The blue text is the id of each service. But guess what? Service id's are much less important in Symfony 3.3... because we almost always rely on type-hints and autowiring.
Re-run the command again with a new
php bin/console debug:container --types
Voilà! This is a list of all valid type-hints that you can use for autowiring. This
is awesome. If you search for "encoder", you'll find one called
This is the type-hint we should use! Symfony ships with this alias to enable autowiring.
Cool! Let's find out where we're using this:
git grep UserPasswordEncoder
LoginFormAuthenticator. Open up
Interface to the end of the
use statement, and also the type-hint:
|... lines 1 - 7|
|class HashPasswordListener implements EventSubscriber|
|... lines 12 - 13|
|public function __construct(UserPasswordEncoderInterface $passwordEncoder)|
|... line 16|
|... lines 18 - 63|
LoginFormAuthenticator and do the exact same thing: update the
and the argument:
|... lines 1 - 10|
|... lines 12 - 15|
|class LoginFormAuthenticator extends AbstractFormLoginAuthenticator|
|... lines 18 - 22|
|public function __construct(FormFactoryInterface $formFactory, EntityManager $em, RouterInterface $router, UserPasswordEncoderInterface $passwordEncoder)|
|... lines 25 - 28|
|... lines 30 - 78|
Ok, go back to the browser! Refresh, and watch those 10 deprecations. Bam! 8 deprecations!
If you check the list now, we still have one more autowiring deprecation. This
time, apparently, it's unhappy about an
Same question as before: is there a better type-hint to use? Let's find out:
php bin/console debug:container --types
Search for EntityManager and... boom! There is an
This is the officially supported type-hint.
Ok, we know the fix: update our
EntityManager type hints to
But... there's another solution! If you want, it is totally ok to type-hint
To make this work with autowiring, we can create an alias.
Doctrine\ORM\EntityManager class name. Then, find your editor and open
services.yml. Add the alias:
Doctrine\ORM\EntityManager aliased to
and then copy the target service id:
|... lines 1 - 5|
|... lines 7 - 26|
|# alias to allow this type to be autowired|
|... line 28|
|... lines 30 - 45|
We have full control over autowiring. With aliases, we can configure exactly which service we want to use for each type-hint. No magic.
Ok, refresh the page one more time! Got it! 8 deprecations now down to 7. The rest of the deprecations are related to other parts of our code. I'll leave those as homework.