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.
Inhaltsverzeichnis
- 1. Warum API Platform 4 Boilerplate eliminiert
- 2. Installation und Erstkonfiguration
- 3. API-Ressourcen mit PHP-Attributen deklarieren
- 4. Operationen gezielt steuern und anpassen
- 5. Filterung, Sortierung und Pagination
- 6. Security: Zugriff auf Ressourcen und Operationen
- 7. GraphQL out of the box aktivieren
- 8. Eigene Provider und Processor für Geschäftslogik
- 9. API Platform vs. manuelle Implementierung
- 10. Zusammenfassung
- 11. FAQ
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.