Binding the Voter to Operations
Binding the Voter to Operations
~12 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026
The ProjectVoter from chapter 52 exists but is NOT called ANYWHERE YET – is_granted() in the security expression connects BOTH.
Using the voter in security
use App\Security\Voter\ProjectVoter;
#[ApiResource(
operations: [
new GetCollection(),
new Get(security: "is_granted('" . ProjectVoter::VIEW . "', object)"),
new Post(security: "is_granted('IS_AUTHENTICATED_FULLY')"),
new Put(security: "is_granted('" . ProjectVoter::EDIT . "', object)"),
new Patch(security: "is_granted('" . ProjectVoter::EDIT . "', object)"),
new Delete(security: "is_granted('" . ProjectVoter::EDIT . "', object)"),
],
// ...
)]
object is a SPECIAL variable that API Platform AUTOMATICALLY fills with the relevant Project instance IN the security expression – EXACTLY the $subject from voteOnAttribute().
Achtung: GetCollection DELIBERATELY has NO security parameter with object – for a collection, there's NO single object to check. FILTERING which items a user sees in the list is a SEPARATE topic (chapter 55).
Testing the behavior
curl -k -i -X PATCH https://localhost/api/projects/1 \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/merge-patch+json' \
-d '{"name": "New name"}'403 Forbidden, as long as getOwner() (chapter 54) does NOT exist yet and the logged-in user does NOT have ROLE_ADMIN – EXACTLY the EXPECTED behavior per the voter logic from chapter 52.
Checking the custom error message
new Patch(
security: "is_granted('" . ProjectVoter::EDIT . "', object)",
securityMessage: 'Only the creator or an administrator may edit this project.',
),Tipp: The string concatenation "is_granted('" . ProjectVoter::EDIT . "', object)" looks UNUSUAL, but is NECESSARY: PHP attributes accept ONLY compile-time constant expressions, NO string interpolation with curly braces like in normal PHP code.