SF
{ }
Symfony · API Platform · REST · GraphQL
API Platform 4: REST und GraphQL
ohne Boilerplate in Symfony

Wer eine REST- oder GraphQL-API in Symfony von Hand aufbaut, schreibt Controller, Serializer-Konfigurationen, Pagination und Fehlerbehandlung selbst. API Platform 4 übernimmt das alles deklarativ — eine PHP-Klasse mit dem richtigen Attribut reicht, um eine vollständige API-Ressource mit Filterung, Pagination und OpenAPI-Dokumentation zu erhalten.

18 Min. Lesezeit Ressourcen · Operationen · Security · Provider · GraphQL Symfony 7.x · API Platform 4.x · PHP 8.3+

1. Warum API Platform 4 Boilerplate eliminiert

Eine REST-API in Symfony ohne Framework zu bauen bedeutet: Controller für jede HTTP-Methode, Serialisierungskonfiguration für jedes Format, Pagination manuell implementieren, OpenAPI-Dokumentation von Hand pflegen und Fehlerantworten konsistent formatieren. Das sind Wochen Arbeit, bevor auch nur eine Zeile Geschäftslogik geschrieben wird. API Platform 4 dreht dieses Verhältnis um: Die Infrastruktur entsteht deklarativ durch Attribute, die Geschäftslogik bleibt der einzige Code, den das Team wirklich schreiben muss.

Der entscheidende Unterschied zu API Platform 2 und 3 liegt in der konsequenten Trennung von API-Ressource und Doctrine-Entity. In Version 4 ist eine Ressource keine Entity mehr — sie ist eine reine PHP-Klasse, die beliebige Datenquellen repräsentieren kann. Das macht API Platform 4 flexibel für Projekte, die keine direkte Datenbankabbildung haben: Legacy-Systeme, Microservices oder externe Datenquellen lassen sich als API-Ressourcen abbilden, ohne Doctrine einzusetzen. Gleichzeitig bleibt die Doctrine-Integration vollständig erhalten — wer Doctrine nutzt, bekommt automatisch CRUD, Filterung und Pagination ohne eine einzige Zeile manuellem Code.

2. Installation und Erstkonfiguration

Die Installation von API Platform 4 in ein bestehendes Symfony-Projekt erfolgt über Composer. Das Paket bringt den Symfony Flex Recipe mit, der alle notwendigen Konfigurationsdateien automatisch anlegt: die Routing-Konfiguration, den API Platform-Bundle-Eintrag in config/bundles.php und die Basiskonfiguration in config/packages/api_platform.yaml. Wer Doctrine nutzt, installiert zusätzlich api-platform/doctrine-orm für die automatische Filterintegration.

Die Grundkonfiguration in api_platform.yaml steuert globale Einstellungen wie das API-Präfix (/api ist Standard), aktivierte Formate (JSON-LD, JSON, HAL, CSV sind möglich), Pagination-Defaults und die OpenAPI-Dokumentation. Für API Platform 4 empfiehlt sich das Format application/ld+json als primäres Format, weil es maschinenlesbare Kontext-Informationen trägt. application/json als Fallback macht die API auch für Clients ohne JSON-LD-Unterstützung zugänglich. Swagger UI und ReDoc sind standardmäßig aktiviert und liefern sofort eine interaktive API-Dokumentation unter /api/docs.

3. API-Ressourcen mit PHP-Attributen deklarieren

Das Herzstück von API Platform 4 ist das #[ApiResource]-Attribut. Eine beliebige PHP-Klasse wird damit zu einer vollständigen API-Ressource — mit automatischen CRUD-Endpunkten, Serialisierung, Deserialisierung und OpenAPI-Dokumentation. Für Doctrine-Entities reicht das Attribut direkt auf der Entity-Klasse: API Platform 4 erkennt automatisch alle Felder, generiert die Endpunkte und verknüpft den Doctrine-Repository für Datenbankoperationen. Für Klassen ohne Doctrine gibt man stattdessen eigene Provider und Processor an.

Serialization Groups steuern, welche Felder in welchem Kontext sichtbar sind. Das Attribut #[Groups(['product:read'])] an einem Feld markiert es für Leseoperationen, #[Groups(['product:write'])] für Schreiboperationen. In der Ressource verweist man mit normalizationContext: ['groups' => ['product:read']] auf diese Gruppen. So sind sensible Felder wie Einkaufspreise oder interne IDs automatisch aus der API-Antwort ausgeblendet, ohne einen eigenen Serializer schreiben zu müssen. Verschachtelte Ressourcen erhalten eigene Gruppen, um zirkuläre Referenzen zu verhindern.

4. Operationen gezielt steuern und anpassen

In API Platform 4 ist jede HTTP-Operation ein eigenes Objekt: Get, GetCollection, Post, Put, Patch und Delete aus dem Namespace ApiPlatform\Metadata. Jede Operation kann individuell konfiguriert werden — mit eigenem Pfad, Serialisierungskontext, Security-Ausdruck, Validierungsgruppen und Custom-State-Provider. Das ermöglicht präzise Kontrolle: Die Listenoperation liefert nur Felder für Übersichten, die Detailansicht liefert alle Felder, und die Schreiboperation validiert mit einer anderen Constraint-Gruppe als die Erstellungsoperation.

Benutzerdefinierte Endpunkte, die keine CRUD-Semantik haben, implementiert man als Post-Operation mit eigenem Pfad und eigenem Processor. Das klassische Beispiel: eine /api/products/{id}/publish-Operation, die einen Status ändert und eine E-Mail auslöst. Der Processor empfängt das deserialisierte Objekt, führt die Geschäftslogik aus und gibt das veränderte Objekt zurück. API Platform 4 übernimmt Serialisierung und HTTP-Antwort automatisch — der Processor enthält ausschließlich Domänenlogik.

5. Filterung, Sortierung und Pagination

Filterung und Sortierung deklariert man in API Platform 4 ebenfalls über Attribute — kein Controller, kein Query-Builder-Code. Der SearchFilter von api-platform/doctrine-orm fügt Query-Parameter für Textsuche hinzu: ?name=laptop filtert automatisch über ein LIKE-Statement, ?category.name=elektronik traversiert Relationen. Der OrderFilter erlaubt Sortierung über Query-Parameter wie ?order[price]=asc. RangeFilter für numerische Bereiche, DateFilter für Zeitstempel und BooleanFilter für Boolean-Felder sind ebenfalls im Paket enthalten und brauchen nur deklariert zu werden.

Pagination ist in API Platform 4 standardmäßig aktiv und liefert Hydra-konforme Antworten mit hydra:totalItems, hydra:view und Links auf erste, letzte, nächste und vorherige Seite. Cursor-basierte Pagination über CursorBasedPaginator ist für große Datensätze verfügbar, bei denen Offset-Pagination zu langsam wird. Beide Ansätze lassen sich per Ressource oder global konfigurieren. Wer die Pagination für eine spezifische Operation deaktivieren will, setzt paginationEnabled: false direkt am Operation-Objekt.

6. Security: Zugriff auf Ressourcen und Operationen

Die Security-Integration von API Platform 4 basiert auf Symfony's Security-Komponente und Voter-System. Auf Ressourcenebene definiert man mit dem security-Parameter einen Security-Ausdruck, der für alle Operationen gilt: "is_granted('ROLE_USER')" schützt die gesamte Ressource. Auf Operationsebene überschreibt man diesen Ausdruck für einzelne Endpunkte — die Listenoperation ist öffentlich, die Detailansicht erfordert Authentifizierung, der Schreibzugriff erfordert eine spezifische Rolle. Dieses feine Granulat vermeidet Global-Firewall-Konfigurationen und hält die Zugriffskontrolle nah an der Ressource.

Der Parameter securityPostDenormalize schützt Operations-Inputs nach der Deserialisierung: Das eingehende Objekt ist dann bereits verfügbar und kann im Security-Ausdruck referenziert werden. Ein typischer Anwendungsfall: "object.getOwner() == user" prüft, ob der eingeloggte Benutzer der Eigentümer der Ressource ist — bevor die Datenbankoperation ausgeführt wird. Für komplexe Zugriffsregeln implementiert man einen Symfony-Voter, der dann per is_granted('EDIT', object) im Security-Ausdruck aufgerufen wird. Die Voter-Klasse enthält die Prüflogik sauber getrennt von der API Platform-Konfiguration.

7. GraphQL out of the box aktivieren

API Platform 4 liefert GraphQL als optionales Extra-Paket. Nach der Installation von api-platform/graphql ist der GraphQL-Endpunkt unter /api/graphql sofort aktiv — ohne weitere Konfiguration. Alle Ressourcen, die für REST deklariert sind, erscheinen automatisch auch im GraphQL-Schema. Queries für einzelne Objekte und Collections, Mutations für Erstellung, Aktualisierung und Löschung sowie Subscriptions für Echtzeit-Updates sind alle verfügbar. GraphiQL, die interaktive GraphQL-IDE, ist standardmäßig unter /api/graphql zugänglich.

Auf Operationsebene steuert man GraphQL-Spezifika über das GraphQlOperation-Attribut. Welche Queries und Mutations verfügbar sind, welche Felder erscheinen und welche Serialisierungsgruppen verwendet werden, ist unabhängig von den REST-Operationen konfigurierbar. Das erlaubt das Szenario, bei dem die REST-API für mobile Clients optimiert ist und die GraphQL-API für den internen Admin-Bereich — beide Schnittstellen teilen sich denselben Domänencode, unterscheiden sich aber in Feldauswahl und Zugriffskontrolle. API Platform 4 managt das Mapping transparent, ohne dass das Team zwei separate APIs entwickeln muss.

8. Eigene Provider und Processor für Geschäftslogik

Der State Provider ist der Einstiegspunkt für das Laden von Daten in API Platform 4. Wenn die automatische Doctrine-Integration nicht ausreicht — etwa weil Daten aus einem externen Service kommen oder komplexe Business-Regeln beim Laden gelten — implementiert man einen eigenen StateProviderInterface. Der Provider gibt entweder ein einzelnes Objekt zurück (für Get-Operationen) oder ein Paginator-Objekt (für GetCollection). Das Aufrufen des Built-in Doctrine-Providers via Dekoration ist möglich, um ihn um Caching oder Transformationslogik zu erweitern.

Der State Processor ist das Gegenstück für schreibende Operationen. Er empfängt das deserialisierte und validierte Objekt und ist verantwortlich für Persistenz, Event-Dispatching und Notifications. Der Built-in Doctrine-Processor ruft EntityManager::persist() und flush() auf — wer ihn dekoriert, kann vor oder nach dem Flush eigene Aktionen auslösen. Das Subscriber-Muster ist dabei klarer als das Überschreiben des Processors: Der Processor persistiert, der Event-Subscriber sendet E-Mails. API Platform 4 löst beide durch sein eigenes Event-System auf, das Operationskontext, Ressource und HTTP-Methode als Metadaten enthält.

9. API Platform vs. manuelle Implementierung

Der direkte Vergleich zeigt, wo API Platform 4 echte Entwicklungszeit spart und wo manuelle Implementierung überlegen ist. Beide Ansätze haben ihren Platz — die Entscheidung hängt von Projektkomplexität, Team-Erfahrung und Flexibilitätsanforderungen ab.

Aufgabe Manuell (Symfony) API Platform 4 Vorteil
CRUD-Endpunkte 5 Controller-Methoden pro Ressource 1 PHP-Attribut 80 % weniger Code
OpenAPI-Dokumentation Manuell mit nelmio/api-doc-bundle Automatisch generiert Immer aktuell, kein Wartungsaufwand
Filterung QueryBuilder-Code pro Filter #[ApiFilter]-Attribut Deklarativ, keine SQL-Logik
GraphQL-API Separates Schema + Resolver Aus REST-Config generiert Eine Ressource, zwei Protokolle
Nicht-Doctrine-Daten Volle Flexibilität Custom Provider nötig Manuelle Implementierung schneller

Die Tabelle zeigt: API Platform 4 gewinnt bei standardisierten CRUD-APIs mit Doctrine deutlich. Bei sehr individuellen Endpunkten, die kaum REST-Semantik haben, kann ein handgeschriebener Symfony-Controller schneller zum Ziel führen als ein Custom-Provider mit API-Platform-Kontext. Viele Projekte nutzen beide Ansätze: API Platform 4 für die Hauptressourcen, manuelle Controller für spezifische Aktionen wie Passwort-Reset oder Datei-Upload.

Mironsoft

Symfony API-Entwicklung, API Platform Integration und Backend-Architektur

REST- und GraphQL-API mit API Platform 4 aufbauen?

Wir entwickeln skalierbare Symfony-APIs mit API Platform 4 — von der Ressourcen-Architektur über Security und Custom Provider bis zur vollständigen OpenAPI- und GraphQL-Dokumentation für euren Stack.

API-Architektur

Ressourcendesign, Serialisierungsgruppen und Security-Strategie für skalierbare Symfony-APIs

Custom Provider

Eigene State Provider und Processor für komplexe Geschäftslogik und externe Datenquellen

GraphQL-Integration

GraphQL-Schema aus bestehenden REST-Ressourcen generieren und für Frontend-Teams bereitstellen

10. Zusammenfassung

API Platform 4 in Symfony ermöglicht vollständige REST- und GraphQL-APIs durch deklarative PHP-Attribute — ohne manuellen Controller-Code, ohne Query-Builder-Boilerplate und ohne separate OpenAPI-Konfiguration. Das #[ApiResource]-Attribut definiert die Ressource, die #[ApiFilter]-Attribute deklarieren Filterung und Sortierung, und die Security-Ausdrücke steuern Zugriff auf Operations-Ebene. Eigene Provider und Processor halten Geschäftslogik sauber getrennt von der Infrastruktur und ermöglichen Erweiterungen durch Dekorierung statt Überschreiben.

Der größte Hebel liegt in der Konsistenz: Alle Ressourcen folgen denselben Mustern, jede neue Ressource ist in Minuten API-ready, und OpenAPI-Dokumentation sowie GraphQL-Schema sind immer synchron mit der Implementierung. Für Teams, die Symfony bereits einsetzen, ist API Platform 4 die direkteste Route zu einer produktionsreifen API ohne wochenlange Infrastrukturarbeit.

API Platform 4 in Symfony — Das Wichtigste auf einen Blick

Ressourcen-Deklaration

#[ApiResource] auf beliebiger PHP-Klasse genügt für vollständige CRUD-API mit OpenAPI-Doku — kein Controller nötig.

Filterung & Pagination

#[ApiFilter]-Attribute deklarieren Such-, Sortier- und Bereichsfilter. Pagination ist standardmäßig aktiv und Hydra-konform.

GraphQL inklusive

Nach Installation von api-platform/graphql steht das GraphQL-Schema automatisch bereit — kein separates Schema-File.

Erweiterbarkeit

Custom Provider und Processor durch Dekoration erweitern — Built-in-Verhalten bleibt erhalten, Geschäftslogik wird sauber hinzugefügt.

11. FAQ: API Platform 4 und Symfony REST/GraphQL

1Was ist API Platform 4?
PHP-Framework für REST- und GraphQL-APIs in Symfony. Generiert vollständige API-Endpunkte, OpenAPI-Dokumentation und GraphQL-Schemas aus PHP-Klassen mit Attributen — kein Controller-Code nötig.
2Muss ich Doctrine nutzen?
Nein. Custom State Provider erlauben beliebige Datenquellen — externe APIs, Legacy-Systeme oder In-Memory-Daten. Doctrine ist optional und wird als separates Paket installiert.
3GraphQL aktivieren?
composer require api-platform/graphql — danach ist /api/graphql sofort aktiv. Alle REST-Ressourcen erscheinen automatisch im GraphQL-Schema. GraphiQL ist inklusive.
4Security auf einzelne Operationen?
Jede Operation hat einen security-Parameter: security: "is_granted('ROLE_ADMIN')". securityPostDenormalize prüft nach der Deserialisierung und hat Zugriff auf das eingehende Objekt.
5Provider vs. Processor?
Provider lädt Daten für GET-Operationen. Processor verarbeitet Daten für schreibende Operationen. Beide können den Built-in Doctrine-Provider durch Dekorierung erweitern.
6Wie funktioniert Filterung?
#[ApiFilter] deklariert Filter auf der Klasse. SearchFilter für Text, OrderFilter für Sortierung, RangeFilter für Bereiche. Nested Relations wie ?category.name werden automatisch aufgelöst.
7JWT Authentication möglich?
Ja. API Platform ist Security-agnostisch und funktioniert mit lexik/jwt-authentication-bundle, OAuth2 und Symfons Security-Komponente. Der user im Security-Ausdruck zeigt den eingeloggten JWT-User.
8Einzelne Operationen deaktivieren?
Im operations-Array nur die gewünschten Operationen eintragen. Fehlt Delete(), gibt es keinen DELETE-Endpunkt. Jede Operation ist ein eigenes Objekt und kann weggelassen oder individuell konfiguriert werden.
9normalizationContext vs. Serialization Groups?
normalizationContext gibt an, welche Groups beim Serialisieren aktiv sind. Felder mit #[Groups(['product:read'])] erscheinen nur wenn diese Gruppe aktiv ist — so liefert die Collection weniger Felder als die Detailansicht.
10Ist API Platform 4 produktionsreif?
Ja. Seit 2015 aktiv entwickelt, stabile Version 4 unterstützt PHP 8.2+, Symfony 6.4 und 7.x. Wird in produktiven Projekten weltweit eingesetzt. Upgrade-Pfad von Version 3 ist dokumentiert.