Skip to content
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

SF 4.3 - Voters - theirs order and auto-registration as service #411

Open
sabat24 opened this issue Aug 26, 2019 · 2 comments
Open

SF 4.3 - Voters - theirs order and auto-registration as service #411

sabat24 opened this issue Aug 26, 2019 · 2 comments

Comments

@sabat24
Copy link

sabat24 commented Aug 26, 2019

I created new Voter in src\Menu\Voter directory. I was surprised that I didn't have to register that voter as a service in services.yaml. Voter just started to work without any other action from my side. Is it normal behaviour because I used menu directory name which is the directory of the bundle?

My Voter was added before default one to the matcher's voters array. I would like to change the order of voters that my voter would be the last one. Is it possible? If not can I (I mean is it good solution) just create new class and extends Knp\Menu\Matcher\Matcher class to overwrite constructor and reverse order of already added voters?

@stof
Copy link
Collaborator

stof commented Aug 27, 2019

if you autoconfigure your services (which is the default behavior in a Symfony 4 app based on the Flex skeleton), a service implementing the VoterInterface will automatically be tagged as knp_menu.voter. This is why it is working without extra config. It is not related to the namespace of the class.

Voters can have a priority to control their order. But that will require tagging them as voter explicitly (the autoconfigured tag does not specify a priority, which makes it fallback to 0, as done in Symfony core).
Extending the Matcher and reversing the order of voters is not the supported way of doing that (and would break the lazy-loading of voters performed by the injected iterator).

@sabat24
Copy link
Author

sabat24 commented Aug 27, 2019

Thank you for clarification.

Based on what you have described, I have to manually tagged voters and provide priority order. However when I tagged voters manually in services.yaml my custom voter in matcher is duplicated.

app.voter.route:
    class: Knp\Menu\Matcher\Voter\RouteVoter
    arguments: [ '@request_stack' ]
    tags:
      - { name: knp_menu.voter, priority: 0 }
  app.voter.parent:
    class: App\Menu\Voter\RequestParentRouteVoter
    arguments: [ '@request_stack' ]
    tags:
      - { name: knp_menu.voter, priority: 1 }

When matcher is initialized there are 3 voters:

App\Menu\Voter\RequestParentRouteVoter <- custom voter
App\Menu\Voter\RequestParentRouteVoter <- custom voter
Knp\Menu\Matcher\Voter\RouteVoter <- default voter

edited I figured it out where was the problem. Autoconfigured voters are always added to array with index 0. So I have to add default RouteVoter with priority 2 and my custom voter with priority 1.
So the behaviour of duplicated voters is correct. However it leads to a situation that 0-indexed voters could be run twice. Is it ok, because responses of prioritized voters are cached by matcher and there are no performance issues?

The order of voters for item which wasn't recognized is as follows: (first voter to be run is on top)

  1. Knp\Menu\Matcher\Voter\RouteVoter - default voter defined in services with priority 2 - returns null;
  2. App\Menu\Voter\RequestParentRouteVoter - my custom voter defined in services with priority 1 - returns null;
  3. App\Menu\Voter\RequestParentRouteVoter - my custom voter autoloaded by symfony with priority 0 - returns null;
  4. Knp\Menu\Matcher\Voter\RouteVoter - default voter autoloaded by symfony with priority 0 - returns null;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants