Eine eigene Custom-Operation: /projects/{id}/archive
Eine eigene Custom-Operation: /projects/{id}/archive
~16 Min. Lesezeit Zuletzt aktualisiert am 8. August 2026
Die SECHS Standard-Operationen (Kapitel 11) decken CRUD ab – eine Aktion wie "Projekt archivieren" ist WEDER Erstellen NOCH Ersetzen NOCH Löschen, sondern eine EIGENE, benannte Operation.
Das archived-Feld ergänzen
#[ORM\Column]
#[Groups(['project:read'])]
private bool $archived = false;
public function isArchived(): bool
{
return $this->archived;
}
public function setArchived(bool $archived): static
{
$this->archived = $archived;
return $this;
}BEWUSST OHNE project:write – archived soll NICHT über ein normales PATCH gesetzt werden können, SONDERN AUSSCHLIESSLICH über den dedizierten Endpunkt weiter unten.
Die Custom-Operation definieren
use ApiPlatform\Metadata\Post;
use App\State\ArchiveProjectProcessor;
new Post(
uriTemplate: '/projects/{id}/archive',
security: "is_granted('" . ProjectVoter::EDIT . "', object)",
processor: ArchiveProjectProcessor::class,
read: true,
),read: true weist API Platform an, das Project ZUERST wie bei einem GET zu LADEN (über die {id} in der URL), BEVOR der Processor aufgerufen wird – der Voter-Check aus Kapitel 53 funktioniert dadurch GENAUSO wie bei den Standard-Operationen.
Den Processor implementieren
<?php
declare(strict_types=1);
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;
use App\Entity\Project;
use Doctrine\ORM\EntityManagerInterface;
final class ArchiveProjectProcessor implements ProcessorInterface
{
public function __construct(
private readonly EntityManagerInterface $entityManager,
) {
}
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): Project
{
/** @var Project $data */
$data->setArchived(true);
$this->entityManager->flush();
return $data;
}
}DANK read: true ist $data BEREITS das GELADENE Project-Objekt – setArchived(true) gefolgt von flush() reicht, KEIN eigener persist()-Aufruf nötig, da die Entity BEREITS von Doctrine VERWALTET wird.
Die Custom-Operation testen
curl -k -X POST https://localhost/api/projects/1/archive \
-H "Authorization: Bearer $TOKEN"{
"id": 1,
"name": "Website-Relaunch",
"archived": true
}Achtung: POST statt PATCH ist HIER BEWUSST gewählt: die Operation hat SEMANTISCH einen EIGENEN Namen ("archive", kein generisches "update") – eine GÄNGIGE REST-Konvention für Aktionen, die sich NICHT natürlich als reine Feldänderung ausdrücken lassen.
Tipp: GENAU dieses Muster (eigenes Feld OHNE write-Gruppe PLUS dedizierte Custom-Operation) eignet sich für JEDE "Aktion" statt "Zustandsänderung" – z. B. auch für /projects/{id}/restore als GEGENSTÜCK zu archive.