@@ -40,14 +40,20 @@ or extend :class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\Vote
4040which makes creating a voter even easier::
4141
4242 use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
43+ use Symfony\Component\Security\Core\Authorization\Voter\Vote;
4344 use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
4445
4546 abstract class Voter implements VoterInterface
4647 {
4748 abstract protected function supports(string $attribute, mixed $subject): bool;
48- abstract protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool;
49+ abstract protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null ): bool;
4950 }
5051
52+ .. versionnadded :: 7.3
53+
54+ The vote parameter in the :method: `Symfony\C omponent\S ecurity\C ore\A uthorization\V oter\V oterInterface::voteOnAttribute ` method
55+ voteOnAttribute method was introduced in Symfony 7.3.
56+
5157.. _how-to-use-the-voter-in-a-controller :
5258
5359.. tip ::
@@ -140,6 +146,7 @@ would look like this::
140146 use App\Entity\Post;
141147 use App\Entity\User;
142148 use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
149+ use Symfony\Component\Security\Core\Authorization\Voter\Vote;
143150 use Symfony\Component\Security\Core\Authorization\Voter\Voter;
144151
145152 class PostVoter extends Voter
@@ -163,12 +170,14 @@ would look like this::
163170 return true;
164171 }
165172
166- protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
173+ protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null ): bool
167174 {
168175 $user = $token->getUser();
176+ $vote ??= new Vote();
169177
170178 if (!$user instanceof User) {
171179 // the user must be logged in; if not, deny access
180+ $vote->reasons[] = 'The user is not logged in.';
172181 return false;
173182 }
174183
@@ -215,11 +224,12 @@ To recap, here's what's expected from the two abstract methods:
215224 return ``true `` if the attribute is ``view `` or ``edit `` and if the object is
216225 a ``Post `` instance.
217226
218- ``voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token) ``
227+ ``voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null ) ``
219228 If you return ``true `` from ``supports() ``, then this method is called. Your
220229 job is to return ``true `` to allow access and ``false `` to deny access.
221- The ``$token `` can be used to find the current user object (if any). In this
222- example, all of the complex business logic is included to determine access.
230+ The ``$token `` can be used to find the current user object (if any). The ``$vote ``
231+ argument can be used to add a reason to the vote. In this example, all of the
232+ complex business logic is included to determine access.
223233
224234.. _declaring-the-voter-as-a-service :
225235
@@ -256,7 +266,7 @@ with ``ROLE_SUPER_ADMIN``::
256266 ) {
257267 }
258268
259- protected function voteOnAttribute($attribute, mixed $subject, TokenInterface $token): bool
269+ protected function voteOnAttribute($attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null ): bool
260270 {
261271 // ...
262272
0 commit comments