@@ -40,14 +40,20 @@ or extend :class:`Symfony\\Component\\Security\\Core\\Authorization\\Voter\\Vote
40
40
which makes creating a voter even easier::
41
41
42
42
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
43
+ use Symfony\Component\Security\Core\Authorization\Voter\Vote;
43
44
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
44
45
45
46
abstract class Voter implements VoterInterface
46
47
{
47
48
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;
49
50
}
50
51
52
+ .. versionadded :: 7.3
53
+
54
+ The `$vote ` parameter in the :method: `Symfony\\ Component\\ Security\\ Core\\ Authorization\\ Voter\\ VoterInterface::voteOnAttribute ` method
55
+ was introduced in Symfony 7.3.
56
+
51
57
.. _how-to-use-the-voter-in-a-controller :
52
58
53
59
.. tip ::
@@ -140,6 +146,7 @@ would look like this::
140
146
use App\Entity\Post;
141
147
use App\Entity\User;
142
148
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
149
+ use Symfony\Component\Security\Core\Authorization\Voter\Vote;
143
150
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
144
151
145
152
class PostVoter extends Voter
@@ -163,12 +170,14 @@ would look like this::
163
170
return true;
164
171
}
165
172
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
167
174
{
168
175
$user = $token->getUser();
176
+ $vote ??= new Vote();
169
177
170
178
if (!$user instanceof User) {
171
179
// the user must be logged in; if not, deny access
180
+ $vote->reasons[] = 'The user is not logged in.';
172
181
return false;
173
182
}
174
183
@@ -197,7 +206,13 @@ would look like this::
197
206
private function canEdit(Post $post, User $user): bool
198
207
{
199
208
// this assumes that the Post object has a `getOwner()` method
200
- return $user === $post->getOwner();
209
+ if ($user === $post->getOwner()) {
210
+ return true;
211
+ }
212
+
213
+ $vote->reasons[] = 'You are not the owner of the Post.';
214
+
215
+ return false;
201
216
}
202
217
}
203
218
@@ -215,11 +230,12 @@ To recap, here's what's expected from the two abstract methods:
215
230
return ``true `` if the attribute is ``view `` or ``edit `` and if the object is
216
231
a ``Post `` instance.
217
232
218
- ``voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token) ``
233
+ ``voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null ) ``
219
234
If you return ``true `` from ``supports() ``, then this method is called. Your
220
235
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.
236
+ The ``$token `` can be used to find the current user object (if any). The ``$vote ``
237
+ argument can be used to add a reason to the vote. In this example, all of the
238
+ complex business logic is included to determine access.
223
239
224
240
.. _declaring-the-voter-as-a-service :
225
241
@@ -256,7 +272,7 @@ with ``ROLE_SUPER_ADMIN``::
256
272
) {
257
273
}
258
274
259
- protected function voteOnAttribute($attribute, mixed $subject, TokenInterface $token): bool
275
+ protected function voteOnAttribute($attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null ): bool
260
276
{
261
277
// ...
262
278
0 commit comments