Skip to content

Update voters.rst #20397

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

Open
wants to merge 1 commit into
base: 5.4
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 64 additions & 9 deletions security/voters.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,74 @@ which makes creating a voter even easier::
abstract protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool;
}

.. _how-to-use-the-voter-in-a-controller:
The Cacheable Voter Interface
-----------------------------
When Symfony calls the ``isGranted()`` method during runtime, it checks each voter
until it meets the access decision strategy set by the configuration.
While this generally works well, it can slow down performance in some cases.

Imagine a backend displaying 20 items, each with 6 properties and 3 actions
(like edit, show, delete). Checking permissions for all these requires 180 calls
to each voter. With 5 voters, that's 900 calls.

Usually, voters only need to focus on a specific permission (e.g., ``EDIT_BLOG_POST``)
or object type (e.g., ``User``). This focus makes voters cacheable by implementing a
:class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\CacheableVoterInterface`

namespace Symfony\Component\Security\Core\Authorization\Voter;

interface CacheableVoterInterface extends VoterInterface
{
public function supportsAttribute(string $attribute): bool;

// $subjectType is the value returned by get_class($subject) or get_debug_type($subject)
public function supportsType(string $subjectType): bool;
}

.. tip::
If your voter returns false for these methods, it will cache this result,
and your voter won't be called again for that attribute or type.

Checking each voter several times can be time consumming for applications
that perform a lot of permission checks. To improve performance in those cases,
you can make your voters implement the :class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\CacheableVoterInterface`.
This allows the access decision manager to remember the attribute and type
of subject supported by the voter, to only call the needed voters each time.
If you extend from the abstract Voter class, you don't need to implement
the interface directly - just override ``supportsAttribute()`` and/or ``supportsType()``.

.. versionadded:: 5.4
For instance, if your voter handles multiple object types but all permissions
are prefixed with ``APPROVE_``, do this:

namespace App\Security;

use Symfony\Component\Security\Core\Authorization\Voter\Voter;

class MyVoter extends Voter
{
public function supportsAttribute(string $attribute): bool
{
return str_starts_with($attribute, 'APPROVE_');
}

// ...
}

The ``CacheableVoterInterface`` interface was introduced in Symfony 5.4.
If your voter handles various permissions for a specific type, do this:

namespace App\Security;

use App\Entity\BlogPost;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;

class MyVoter extends Voter
{
public function supportsType(string $subjectType): bool
{
// you can't use a simple BlogPost::class === $subjectType comparison
// here because the given subject type could be the proxy class used
// by Doctrine when creating the entity object
return is_a($subjectType, BlogPost::class, true);
}

// ...
}

.. _how-to-use-the-voter-in-a-controller:

Setup: Checking for Access in a Controller
------------------------------------------
Expand Down
Loading