Symfony 6.2 will be released at the end of November 2022. This is the first article of the series that shows the most important new features introduced by Symfony 6.2.
Symfony introduced annotations to configure cache, security, templates and Doctrine more than 10 years ago. They were available via an external bundle called SensioFrameworkExtraBundle.
With the introduction of PHP attributes, we turned those annotations into
attributes. However, you still had to install sensio/framework-extra-bundle
package to use them. For example:
1 2 3 4 5 6 7 8 9 10 11
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\Routing\Annotation\Route;
#[Route('/comment/{postSlug}/new', methods: ['POST'], name: 'comment_new')]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
#[ParamConverter('post', options: ['mapping' => ['postSlug' => 'slug']])]
public function addComment(Request $request, Post $post): Response
{
// ...
}
In Symfony 6.2, we've introduced #[Cache]
, #[Template]
, #[IsGranted]
and #[MapEntity]
as native attributes, so you no longer need to install
any external package to use them. #[IsGranted]
replaces and improves the
previous @Security()
annotation and #[MapEntity]
replaces the previous
@ParamConverter
annotation.
In most applications, you will only need to update the imported namespace, without having to change anything in your code:
1 2 3 4
-use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
+use Symfony\Component\Security\Http\Attribute\IsGranted;
-use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
+use Symfony\Component\HttpKernel\Attribute\Cache;
The #[MapEntity]
feature (available when using DoctrineBundle >= 2.7.1) works
just like #[ParamConverter]
: in most situations you don't need to use the
attribute at all, it's automatic.
However, if you previously used #[ParamConverter]
to customize your configuration,
you'll need to make some changes to turn it into the new #[MapEntity]
attribute.
Also, the new attribute is applied to properties, instead of to the entire method:
1 2 3 4 5 6 7 8 9 10 11 12 13
-use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
+use Symfony\Bridge\Doctrine\Attribute\MapEntity;
// ...
-#[ParamConverter('post', options: ['mapping' => ['postSlug' => 'slug']])]
-public function addComment(Request $request, Post $post): Response
+public function addComment(
+ Request $request,
+ #[MapEntity(mapping: ['postSlug' => 'slug'])] Post $post
+): Response
{
// ...
}
We believe that PHP attributes are a great way to add metadata configuration to code. However, if you don't like them, you can skip them and keep configuring things in XML/YAML or directly in PHP code.
It's a good thing ! Thanks:)
Nice! The new MapEntity attribute makes much more sense
The MapEntity attribute looks better than the ParamConverter attribute but when you're used to the SensioFrameworkExtraBundle this is just jarring. When using that you need no attributes whatsoever and the code looks much more readable.
I think there is an issue in the text or I have it all wrong, where it says, and I quote
"In Symfony 6.2, we've introduced #[IsGranted], #[Cache], #[Template] and #[ParamConverter] as native attributes, so you no longer need to install any external package to use them."
I think you guys meant
In Symfony 6.2, we've introduced #[IsGranted], #[Cache], #[Template] and #[MapEntity] as native attributes, so you no longer need to install any external package to use them.
Either MapEntity is a replacement for ParamConverter as explained in the code below or was not mentioned. But something feels wrong.
Either way, this is so cool I always felt SensioFrameworkExtraBundle was that piece of code that felt forced and everything inside it should be part of other bundles or SF it self.
great addition
The behavior of the new
MapEntity
is identical to the oldParamConverter
, the attribute is optional, and when the behavior is enabled in your config, then all your entities will be automatically resolved. But you can fine-tune specific properties (like custom RouteParameter name, or Repository method) with the attribute.It's even better that the
ParamConverter
because, when activated globally in your config, you can also disable the behavior for one controller or two with the attribute (which is not possible withSensioFrameworkExtraBundle
)This looks great!
Are there plans to convert
Sensio\Bundle\FrameworkExtraBundle\Configuration\Security
to Symfony core too?@Jérémy thanks for explaining it with more detail. I've updated the original blog post content to better explain that, in most situations,
MapEntity
is as automatic as the previousParamConverter
.Can the following attribute : #[Entity('document', expr: 'repository.find(did)')] also do without the sensio-bundle and if so how?
I see that #[IsGranted(...)] is also allowing using expressions - so I would be really nice to cover that part in this blog post too - just because many of us have use #[Security(...)] before and now it seems like we don't really need to use that anymore.
Superb.....
Great. Love that.
@Tarmo we have no plan to move the Security annotation to the core, because its architecture is flawed (it is not build on top of the authorization system, which caused many issues when rewriting the internals of the security component in 5.3). However, the new IsGranted attribute of Symfony is much more powerful than the IsGranted annotation of SensioFrameworkExtraBundle and it should allow migrating to it.
Great!
Great! One more step towards the end of the SensioFrameworkExtraBundle which was efficient but a bit of a catch-all :)
Fantastic news!
ParamConverter is/was more than just a way to map an entity though.
It would be nice to mention that for those using custom ParamConverter classes (implementing ParamConverterInterface) without DoctrineBundle, the solution is to migrate them to Argument Resolver classes (implementing ArgumentValueResolverInterface).
@Michel, thanks to Wouter who updated the doc for creating a custom value resolver. https://symfony.com/doc/6.2/controller/value_resolver.html#adding-a-custom-value-resolver
Note that ArgumentValueResolverInterface work directly on the argument injected into the controller. ParamConverter modified the request attributes, which had an impact outside of the controller.
@Tarmo see https://github.com/rectorphp/rector/issues/7583. Let's try to create a Rector for it.
What about the very usufull
request: { converters: true, auto_convert: true }
option (in particular auto_convert: true). Is there an option to achieve that behaviour without the plugin, or annotating each controller action with#[MapEntity
is required?