Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add native Http-based attribute support (Deprecate SensioFrameworkExtraBundle) #45415

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

codedmonkey
Copy link
Contributor

Q A
Branch? 6.1
Bug fix? no
New feature? yes
Deprecations? no (yes for SensioFrameworkExtraBundle)
Tickets Fix #44705
License MIT
Doc PR

While annotations have been part of the Symfony experience for years, support for this has always been dependent of separate libraries. Because of concerns over performance, annotations used by controllers have up to this point been part of SensioFrameworkExtraBundle. With the addition of attributes to PHP, this can finally be addressed directly.

This PR takes the annotation classes and services from SensioFrameworkExtraBundle and adds them to the Symfony core as attribute-based services. Each attribute and their related services have been moved to the most appropriate component:

  • Cache ➡️ Symfony\Component\HttpKernel\Attribute\Cache
  • Entity ➡️ Symfony\Bridge\Doctrine\Attribute\Entity
  • IsGranted ➡️ Symfony\Component\Security\Attribute\IsGranted
  • ParamConverter ➡️ Symfony\Component\HttpKernel\Attribute\ParamConverter
  • Security ➡️ Symfony\Component\Security\Attribute\Security
  • Template ➡️ Symfony\Bridge\Twig\Attribute\Template

Similarly, services have been divided over the FrameworkBundle, SecurityBundle and TwigBundle for their respective attributes (the DoctrineBundle has to be updated as well).

Originally, the SensioFrameworkExtraBundle used the ControllerListener class to loop through the configured controller annotations and add its metadata to the request in it's attributes parameter bag, after which a separate event listener would pick up the metadata for a specific annotation to execute the expected logic. Because the event listeners now reside in different components there isn't any way to handle all attributes at once, so each listener is now responsible for reading the attributes on the controller for itself.

Drawbacks

There are a few small drawbacks by deprecating the SensioFrameworkExtraBundle.

It used to be possible to disable support for each attribute individually, but since a toggle for this wasn't added when integrating the Route annotation in Symfony, I didn't add those here either. There is a difference though, routing attributes are (usually) only read during compilation and are cached afterwards. The attributes added in this PR are all read at runtime. Additionally, each event listener has to read the the controller class for attributes separately and is added to the container by default. I am not qualified to say what impact this will have on general performance.

Annotations that are based on the ConfigurationInterface from the SensioFrameworkExtraBundle have their metadata stored in the request's attributes parameter bag. Because the event listeners get the metadata directly from the controller now, this has been removed for most attributes in this PR. This means it's no longer possible to manipulate this metadata before the respective event listener, which is technically a BC break. In the case where metadata is used by its event listener from multiple events, the metadata is still stored in the request.

Remaining Tasks

  • Copy functional tests
  • Refactor existing Routing annotation code (to emphasize attributes)
  • Add Entity attribute services to DoctrineBundle
  • Create PR for SensioFrameworkExtraBundle with deprecation messages
  • Clean up code (update code style, refactor outdated practices)
  • Create PR for documentation
  • Update changelogs

@carsonbot carsonbot added Status: Needs Review Feature RFC RFC = Request For Comments (proposals about features that you want to be discussed) labels Feb 13, 2022
@carsonbot carsonbot added this to the 6.1 milestone Feb 13, 2022
@carsonbot carsonbot changed the title [RFC] Add native Http-based attribute support (Deprecate SensioFrameworkExtraBundle) Add native Http-based attribute support (Deprecate SensioFrameworkExtraBundle) Feb 13, 2022
@nicolas-grekas
Copy link
Member

Wow big PR thanks for tackling this!
I think we first need to solve the factorization of the attribute extraction logic.
To me this should be lazy and central.
I suppose we need to put the attributes in a _controller_attributes request attribute, that should be computed by a service that listener that need the info should require to compute _controller_attributes if it's not set.
Or another design if you have another proposal of course!
Would you like to give it a try in a separate PR?

@codedmonkey
Copy link
Contributor Author

codedmonkey commented Feb 13, 2022

In case it needs to be lazy and central, it might be a good idea to incorporate it in the Routing component.

It would make it possible for the attributes to be placed in an already existing cache, whichever configuration format the developer uses to configure their routes. Plus it would make the following possible when attribute support is disabled:

return function (RoutingConfigurator $routes) {
    $routes->add('foo', '/foo')
        ->controller([BlogApiController::class, 'show'])
        ->attributes([
            new Cache(maxage: 15),
            new Template(template: 'templates/foo.html.twig')
        ])
    ;
};

See https://github.com/sensiolabs/SensioFrameworkExtraBundle/issues/140 for this being requested 10 years ago.

@nicolas-grekas
Copy link
Member

Routing is mostly unaware of the concept of controllers so I wouldn't add to it. HttpKernel is just fine for that to me.

Copy link
Member

@jderusse jderusse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The plan is to remove paramConverter but we never finished it (see #40333 (comment)).

We also have issues (ie. #40333) because of conflict between paramConvert + Argument Resolver (I didn't checked if this PR solved this issue)

I have the feeling that ParamConverter and ArgumentResolver provide the same features, or, at least, in most of the cases are used in the same way (ie Entity resolver). They are confusing for end-users and IMHO one should and one should be removed.

I'm 👍 for deprecating the SensioFrameworkExtraBundle, and finishing the migration to ArgumentResover

For the record, there is PR that adds support for Doctrine Entity (#43854). 😞 I need to find time to finish it.

@derrabus
Copy link
Member

Thank you very much for all the effort you've put into this PR!

One reason why FrameworkExtraBundle should be deprecated was that Symfony already has a replacement for the ParamConverter mechanism:

https://symfony.com/doc/current/controller/argument_value_resolver.html

Now in your PR, I see that ParamConverters have been resurrected. Can you please have a look if you can build those attributes with argument value resolvers instead?

@codedmonkey
Copy link
Contributor Author

See #45457 for the controller attribute mechanism suggested by Nicolas :)

@rosier
Copy link
Contributor

rosier commented Mar 24, 2022

The best practices docs tells us not to use the @Template annotation.

It makes me question whether Template should even be migrated to an attribute ?

@stof
Copy link
Member

stof commented Mar 24, 2022

Also, I would not migrated the Security attribute as is. The implementation of this attribute is currently a hack, as it does not rely on triggering the authorization system to perform the security check (instead, it duplicates part of that system, which broke when switching to the new security system).
The best practice for using that attribute is to restrict yourselves to using is_granted inside the expression (or to switch to IsGranted for all cases where it can be used, as that attribute does not hack the authorization system).

To me, this should rather be left out, adding a few advanced features to IsGranted:
The one I would need personally is having a subject_expression feature, allowing to use ExpressionLanguage to build the subject being voted on (but with a better approach than Security where we have clashes between controller argument names and built-in variables of the expression) when we need a more complex vote.
Another one that could be needed is a way to specify that the permission being checked is an expression for ExpressionVoter (but this may be supported already on PHP 8.1 when using attributes rather than annotations, but using new Expression)

@fabpot fabpot modified the milestones: 6.1, 6.2 May 20, 2022
@nicolas-grekas
Copy link
Member

@codedmonkey would you be up to resume this work on top of #46001? It'd suggest splitting this PR in many, one per attribute.
Closing here meanwhile for history.

@codedmonkey
Copy link
Contributor Author

I'll see what I can do :)

@nicolas-grekas
Copy link
Member

Cool thanks, I'm looking forward to your PRs 🙏
I already started with #[Cache], please check # #46880.

@nicolas-grekas
Copy link
Member

I implemented #[Template] in #46906 and #[IsGranted] in #46907
I won't be able to work on the other ones before August so feel to follow up with the other attributes!

nicolas-grekas added a commit that referenced this pull request Jul 12, 2022
This PR was merged into the 6.2 branch.

Discussion
----------

[Security] Add `#[IsGranted()]`

| Q             | A
| ------------- | ---
| Branch?       | 6.2
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Tickets       | Part of #44705
| License       | MIT
| Doc PR        | -

Extracted from #45415 (and modernized a lot).

I did not implement the proposals from Stof to keep this first iteration simple. I'd appreciate help to improve the attribute in a follow up PR 🙏

Commits
-------

bf8d75e [Security] Add `#[IsGranted()]`
nicolas-grekas added a commit that referenced this pull request Jul 12, 2022
…nder arrays returned by controllers (nicolas-grekas)

This PR was merged into the 6.2 branch.

Discussion
----------

[TwigBridge] Add `#[Template()]` to describe how to render arrays returned by controllers

| Q             | A
| ------------- | ---
| Branch?       | 6.2
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Tickets       | Part of #44705
| License       | MIT
| Doc PR        | -

Extracted from #45415 (and modernized a lot).

Unlike the``@Template`` annotation, this attribute mandates a template name as argument. This removes the need for any template-guesser logic, making things explicit.

Using the attribute also turns `FormInterface` instances into `FormView`, adjusting the status code to 422 when a non-valid form is found in the parameters, similarly to what `AbstractController::render()` does.

Commits
-------

c252606 [TwigBridge] Add `#[Template()]` to describe how to render arrays returned by controllers
chalasr added a commit that referenced this pull request Jul 12, 2022
…HTTP cache headers on controllers (nicolas-grekas)

This PR was merged into the 6.2 branch.

Discussion
----------

[HttpKernel] Add `#[Cache()]` to describe the default HTTP cache headers on controllers

| Q             | A
| ------------- | ---
| Branch?       | 6.2
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Tickets       | Part of #44705
| License       | MIT
| Doc PR        | -

Extracted from #45415 (and modernized a lot).

I'd appreciate any help for porting the other attributes following this leading PR 🙏

Commits
-------

acd4fa7 [HttpKernel] Add `#[Cache]` to describe the default HTTP cache headers on controllers
@codedmonkey
Copy link
Contributor Author

@nicolas-grekas I think you've got them all covered since the ParamConverter and Security annotations have been discusses and rejected by the community. Thank you for all the hard work :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature RFC RFC = Request For Comments (proposals about features that you want to be discussed) Status: Needs Review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[RFC] Abandon FrameworkExtraBundle
8 participants