Automatically Setting the owner Field
Automatically Setting the owner Field
~14 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026
The voter from chapter 52 needs $project->getOwner() – this chapter adds the field AND ensures it gets set AUTOMATICALLY on creation, NEVER by the client itself.
Adding the owner field
use App\Entity\User;
// ... inside the class:
#[ORM\ManyToOne]
#[ORM\JoinColumn(nullable: false)]
#[Groups(['project:read'])]
private ?User $owner = null;
public function getOwner(): ?User
{
return $this->owner;
}
public function setOwner(User $owner): static
{
$this->owner = $owner;
return $this;
}Achtung: DELIBERATELY WITHOUT project:write in the groups – if owner were WRITABLE, ANY user could claim, when creating a project, that ANOTHER user is the owner. The field is set INSTEAD via a state processor.
Writing an owner processor
<?php
declare(strict_types=1);
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;
use App\Entity\Project;
use App\Entity\User;
use Symfony\Bundle\SecurityBundle\Security;
final class ProjectOwnerProcessor implements ProcessorInterface
{
public function __construct(
private readonly ProcessorInterface $persistProcessor,
private readonly Security $security,
) {
}
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): mixed
{
if ($data instanceof Project && null === $data->getOwner()) {
$user = $this->security->getUser();
if ($user instanceof User) {
$data->setOwner($user);
}
}
return $this->persistProcessor->process($data, $operation, $uriVariables, $context);
}
}EXACTLY the same wrapping pattern as UserPasswordHasherProcessor from chapter 48 – Symfony\Bundle\SecurityBundle\Security provides the CURRENTLY logged-in user, EXACTLY like $this->getUser() in a classic Symfony controller.
use App\State\ProjectOwnerProcessor;
#[ApiResource(
processor: ProjectOwnerProcessor::class,
// ...
)]
Testing the complete behavior
curl -k -X POST https://localhost/api/projects \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"name": "My new project"}'The created project has owner AUTOMATICALLY set to the LOGGED-IN user – a PATCH ON THIS project by the SAME user now WORKS (chapter 53), by a DIFFERENT user without ROLE_ADMIN STILL does NOT.
Tipp: Don't forget the migration: owner_id as a NEW, NOT-NULLABLE column requires EITHER a default value in the migration for ALREADY-existing test data, OR a PRIOR doctrine:database:drop --force && doctrine:database:create, to start fresh with an EMPTY database.