Symfony: Passing more than one Security attribute to AccessDecisionManager::decide() is deprecated

Since Symfony 5 is out in the wild for a while now, I wanted to update to Symfony 4.4 and prepare for the upgrade.

I guess you all know about the Symfony’s future compatibility promise – if your codebase works on 4.4 without deprecation notices, chances are it will work on 5.0 too

Then I ran into this cryptic deprecation notice:

Passing more than one Security attribute to Symfony\Component\Security\Core\Authorization\AccessDecisionManager::decide() is deprecated since Symfony 4.4. Use multiple decide() calls or the expression language (e.g. “has_role(…) or has_role(…)”) instead

I say “cryptic” because I haven’t used AccessDecisionManager::decide, like, never.
I’ve traced this to this @IsGranted annotation, that was using multiple roles.

Then I changed it to @Security annotation, according to the docs and the suggestion in the deprecation notice to this:

And here comes the funny part…

Even though the difference in syntax between @IsGranted and @Security looked so subtle (using or instead of an array), the new, human readable version, is actually an Expression.
And to parse it, I needed a Symfony ExpressionLanguage Component, as noted by an informative exception that broke my tests:

To use the @Security tag, you need to use the Security component 2.4 or newer and install the ExpressionLanguage component.

Note to self: Make a PR to the official docs, since there was no sign of that component being needed. Done that, but seems Symfony prefers to inform you about dependencies through exceptions, not documentation.

Thankfully, thats quickly fixed:
composer require symfony/expression-language

And that’s it! Changed annotations in all the places where multiple roles were used and no more deprecation notice 🙂