🔨 API Platform Conference 2025: Ein Rückblick auf zwei intensive Tage mit Fokus auf das Symfony- und PHP-Ökosystem
der 20. September 2025
Die API Platform Conference 2025 fand am 18. und 19. September statt. Zwei Tage lang trafen sich die Symfony-, PHP- und API-Communitys zu Keynotes, Feedback und leidenschaftlichen Diskussionen. Hier ist eine Zusammenfassung der einzelnen Vorträge, um die wichtigsten Erkenntnisse der Veranstaltung im Überblick zu behalten.
🎤 Tag 1 – 18. September
🔑 Eröffnungs-Keynote – Kévin Dunglas
Wir stellen die neuen Funktionen der API-Plattform 4.2 vor, mit Schwerpunkt auf Automatisierung, Echtzeit-Support (Mercury, SSE) und LLM-Integration. Eine klare Vision für die Zukunft des Ökosystems.
🔑 Keynote von Kévin Dunglas – 10 Jahre API-Plattform und ein wichtiges neues Feature
Um das 10-jährige Jubiläum der API Platform zu feiern, betrat ihr Erfinder Kevin Dunglas in Lille die Bühne mit einer wichtigen Ankündigung: einer neuen Funktion, die von API Platform und FrankenPHP gemeinsam genutzt wird.
👨💻 Eine gemeinschaftliche und kooperative Reise
Kévin erinnerte sich an seine vielen Rollen: Betreuer von Symfony und PHP, Mitbegründer der Genossenschaft Les-Tilleuls.coop und Initiator von Projekten wie Mercure, FrankenPHP und mehreren Symfony-Komponenten. Er betonte das kooperative Modell seines Unternehmens, in dem Entscheidungen demokratisch getroffen und Gewinne geteilt werden.
🎂 Zehn Jahre API-Plattform
- Es begann als einfaches Symfony-Paket mit 2000 Codezeilen zur Bereitstellung einer REST-API. * Heute: eine komplette Bibliothek, nutzbar mit Symfony, Laravel oder ohne Framework, mit fast 10.000 GitHub-Sternen und fast 1000 Mitwirkenden. * Der Kern des Projekts ist derselbe: Bereitstellung moderner APIs aus einfachen PHP-Klassen bei gleichzeitiger Unterstützung mehrerer Stile.
🌐 Multi-API-Unterstützung
Mit der API-Plattform können Sie jetzt automatisch Folgendes generieren:
- REST (Hydra, HAL, JSON:API) * OpenAPI (maschinenlesbare Beschreibung) * GraphQL * Asynchrone APIs mit Mercure und SSE
Diese Fähigkeit, mehrere API-Stile mit demselben Code zu vereinen, bleibt eine einzigartige Stärke des Frameworks.
💡 Was ist neu: gRPC mit FrankenPHP
Die große Ankündigung war die Ankunft von gRPC im Ökosystem.
- gRPC (von Google entwickelt) ist ein Hochleistungsprotokoll, das auf Protocol Buffers und HTTP/2 basiert. * Vorteile: Stark typisierte, schnelle, effiziente Kommunikation, geeignet für Microservices, IoT und kritische Systeme. * Bisher konnte PHP nicht als gRPC-Server dienen (technische Einschränkung).
👉 Dank FrankenPHP, geschrieben in Go, ist es jetzt möglich:
- Schreiben Sie Go-Erweiterungen für FrankenPHP, * erstellen Sie einen gRPC-Server, der die Geschäftslogik an PHP-Worker delegiert, * kombinieren Sie das Beste aus beiden Welten (Go für die Netzwerkleistung, PHP für die Anwendungslogik).
Ein Prototyp der FrankenPHP gRPC-Erweiterung ist bereits auf Kevins GitHub verfügbar.
📈 Perspektiven
- Generieren Sie automatisch Protodateien aus API-Ressourcenentitäten. * Integrieren Sie gRPC direkt als von der API-Plattform unterstütztes Format. * Erleichtern Sie die Interoperabilität zwischen PHP, Go und anderen Sprachen.
🤝 Eine Gemeinschaft über alles
Kevin betonte abschließend, dass die wahre Stärke der API-Plattform ihre Community sei: Mitwirkende, Trainer und Entwickler. Er würdigte außerdem Ryan Reza, einen wichtigen Beitragenden, der kürzlich verstorben ist, und rief dazu auf, seine Familie durch eine Spendenaktion zu unterstützen.
📌 Zusammenfassend
Die Eröffnungs-Keynote feierte 10 Jahre Innovation und Community rund um die API-Plattform und kündigte gleichzeitig eine wichtige Entwicklung an: ➡️ die Einführung von gRPC im Ökosystem über FrankenPHP. Dieser Fortschritt bringt Symfony, Laravel und die PHP-Welt der Zukunft moderner APIs noch näher.
⚡ Leistung
- 180.000 Anfragen pro Sekunde einfach erklärt – Xavier Leune Ein lehrreicher Vortrag, der die Techniken hinter extremer Leistung detailliert beschreibt: feinkörniges Verbindungsmanagement, Wahl der Netzwerkarchitektur und die Bedeutung der Laufzeit.
Hier ist eine klare, strukturierte und sofort einsatzbereite Version des Vortrags von Xavier Leune (FR). Ich habe den Vortrag neu strukturiert, die technischen Ideen verdeutlicht und die Demonstrationen und praktischen Tipps beibehalten – und dabei den pädagogischen Ton beibehalten.
Netzwerkleistung und Parallelität in PHP
(Kern, nicht blockierende E/A, TCP/TLS, HTTP/2/3, DNS, Fork und Speicherfreigabe)
Hallo, ich bin Xavier Leune. Heute sprechen wir über ganz praktische Dinge: Wie man Tausende von Anfragen von PHP effizient bearbeitet, warum sich die CPU so verhält, wie sie es tut, und welche Techniken man anwenden kann, um Verbindungsprobleme zu vermeiden.
Kontext: Warum wir CPU-Zeit verschwenden, wenn wir auf Antworten warten
Bei vielen Netzwerkanfragen vergeht die meiste Zeit mit Warten (E/A) – nicht mit eigentlicher Rechenleistung. In einem typischen synchronen Skript werden jedoch viele CPU-Zyklen verbraucht, nur weil es in einer Schleife den E/A-Status abfragt: immer wieder „false“, „false“, „false“. Ein typisches Ergebnis: Sie erhalten 10 Sekunden Echtzeit, verbrauchen aber 20 Sekunden CPU-Leistung, weil die Schleifen vergeblich laufen.
Kernel / Nicht blockierende IO: Geben Sie die CPU frei
Die Lösung besteht darin, die Wartezeit vom Kernel (oder der Laufzeitumgebung) verarbeiten zu lassen, anstatt sie im Userland auszuführen. Zwei Ansätze:
- Naives Polling: Aktive Schleife, die ohne Pause prüft → CPU-intensiv. * Select / epoll / kqueue: Wir warten, bis der Kernel ein bereites IO signalisiert. In PHP reduziert die Verwendung des Äquivalents (select, stream_select oder libs/event) Iterationen und CPU-Zeit drastisch: Wir reduzieren die Iterationen von Tausenden auf einige Dutzend.
Konkret: Ersetzen Sie eine while (!done) { check(); }
-Schleife durch ein select
, das das Skript aufweckt, wenn Ereignisse zu verarbeiten sind.
Achtung Decke: Verbindungen herstellen
Das Herstellen einer TCP-Verbindung kostet: Systemressourcen, Sockets, Handler usw. Wenn Sie in kurzer Zeit 2k-, 4k- oder 8k-Verbindungen öffnen, riskieren Sie:
- vollständiger serverseitiger Rückstand → SYN, das nie verarbeitet wird; * clientseitige Timeouts (5–15 s), da die Verbindung nie hergestellt wurde; * Fehler, die nur im großen Maßstab sichtbar sind (Timeouts, Ablehnungen, Abbrüche).
Tipp: Drosseln Sie die Anzahl aktiver Verbindungen. Begrenzen Sie beispielsweise die Anzahl von N gleichzeitigen Verbindungen und starten Sie neue Verbindungen nur, wenn eine verfügbar ist. Erhöhen Sie N schrittweise basierend auf dem tatsächlichen Verhalten.
TLS (HTTPS): ein zusätzlicher kostspieliger Schritt
Nach dem TCP-Handshake fügt TLS Roundtrips (Handshakes) und kryptografische Berechnungen hinzu. Dies erhöht die Verbindungslatenz. Wenn Sie die Anzahl der kurzen verschlüsselten Verbindungen vervielfachen, steigen die Kosten pro Anfrage erheblich.
- Verwenden Sie Verbindungen nach Möglichkeit wieder (Verbindungspooling/Keep-Alive). * Wenn Sie viele Verbindungen öffnen müssen, berechnen Sie die TLS-Kosten und testen Sie mit Ihrer tatsächlichen Last.
Dekorrelation von Verbindungen ↔ Anfragen: Multiplexing & Protokoll
Geschichte:
- HTTP/1.x: eine Anfrage = eine Verbindung (oder begrenztes Pipelining) → viele Verbindungen. * HTTP/2: Multiplexing auf einer einzigen Verbindung (mehrere Streams), unabhängige Reihenfolge, reduzierte Anzahl von Verbindungen. * HTTP/3 (QUIC): über UDP, leichtere Verbindung, integrierte TLS-Unterstützung, konzipiert für mobile Netzwerke mit hoher Latenz und hohem Verlust.
Praktische Konsequenzen:
- Mit HTTP/2 reduzieren wir die Anzahl der Verbindungen und erhöhen die Anforderungsrate(n) auf einem gut konfigurierten Server erheblich. * Mit HTTP/3 gewinnen wir an Ausfallsicherheit in instabilen Netzwerken und verringern die Latenz in bestimmten mobilen Szenarien, aber die Client <-> Server-seitigen Implementierungen können je nach Stacks immer noch weniger ausgereift sein als HTTP/2.
TCP: Neuübertragung und Head-of-Line-Blockierung
Bei (zuverlässigem) TCP überträgt TCP den gesamten Block erneut, wenn die dritte Antwort eines Pakets verloren geht. Dies kann andere Multiplex-Antworten blockieren, wenn kein moderneres Protokoll (QUIC/HTTP3) verwendet wird. Daher ist QUIC in bestimmten Fällen (mobile Latenz, Datenverluste) interessant. Vorsicht ist jedoch geboten: Server-Client-Implementierungen und Tools müssen ausgereift sein.
DNS und clientseitiger Lastenausgleich
Wenn Ihre Domäne über mehrere A-Einträge (oder mehrere Backends) verfügt, wirkt sich die Art und Weise, wie Sie die IP auflösen, auf Ihre Lastverteilung aus:
- Die DNS-Auflösung bei jeder Anfrage kann die Empfängervielfalt erhöhen (Round-Robin). * Die clientseitige Caching-Auflösung kann die Last auf ein einzelnes Backend konzentrieren. * Manchmal hilft die rotierende DNS-Auflösung (selbstständige Ausführung) bei der Lastverteilung.
Praktischer Tipp: Lösen Sie Backend-IPs vorab auf und erstellen Sie Ihre Abfragen auf diesen IPs, um bei Bedarf ein clientseitiges Round-Robin-Verfahren zu erzwingen.
Messungen und Vergleiche: HTTP/1 vs. HTTP/2 vs. HTTP/3 (Zusammenfassung)
Klassische Beobachtungen zu Belastungstests:
- HTTP/1: Riesige Anzahl von Verbindungen, niedrige RPS pro Socket, hohe Client-CPU. * HTTP/2: Viel weniger echte Verbindungen, sehr hohe RPS (Tausende → Zehntausende). * HTTP/3: Manchmal besser bei mobilen/instabilen Verbindungen; in der Praxis variieren die Ergebnisse je nach Implementierung, aber konzeptionell werden einige TCP-Blockierungen vermieden.
Fazit: HTTP/2 ist oft der beste Kompromiss für die meisten Server→Browser/API-Lasten, außer in Fällen mit mobiler Nutzung/extremer Latenz, in denen HTTP/3 helfen kann – testen Sie es.
CPU auf der Clientseite erhöhen: fork / parallel / pcntl
Manchmal möchten Sie die Client-CPU voll ausnutzen (Lasttests, hohe Verarbeitungsleistung). Optionen in PHP:
- pcntl_fork (Prozessfork): Erstellung von Kindprozessen; einfach, robust; Vorsicht bei gemeinsam genutzten Ressourcen (Sockets, DB). * parallel (Erweiterung): parallele Ausführung in leichten Threads (falls verfügbar). * pthreads (veraltet / nicht CLI), andere Lösungen auf Betriebssystemebene.
Wichtig: Nach einem Fork dürfen die gleichen offenen Verbindungen (Sockets, DB-Handles) nicht ohne Vorsichtsmaßnahmen zwischen Eltern- und Kind-Elementen geteilt werden – das unterbricht den Datenfluss. Zwei Ansätze:
- Öffnen Sie die Verbindung nach der Verzweigung: Jeder Prozess hat seinen eigenen Socket/DB. 2. Schließen und öffnen Sie die Verbindung im Kindprozess erneut: sicher und einfach.
Kommunikation zwischen Prozessen: gemeinsam genutzter Speicher
Beim Forken benötigen Sie eine Möglichkeit zur Synchronisierung/Kommunikation:
- Shared Memory (shmop / SysV shm / ext-shm): Erstellen Sie einen gemeinsam genutzten Speicherbereich zum Lesen/Schreiben von Zeichenfolgen, Zuständen usw. Nützlich, einfach. * Unix-Semaphoren / -Dateien / -Sockets: Alternativen nach Bedarf.
Klassisches Muster:
- übergeordnetes Element erstellt gemeinsamen Speicher (ftok + shmget), * untergeordnetes Element schreibt regelmäßig, * übergeordnetes Element liest/wartet (Poll/Sleep); * Aufräumen am Ende.
Zu beobachtende Ressourcen und Best Practices
- Gleichzeitige Verbindungserstellung begrenzen (Drosselung). * Verbindungen wiederverwenden (Keep-Alive, Pools). * Select/Epoll im nicht blockierenden IO-Modus verwenden – nicht drehen. * TLS-Kosten testen (Handshake): Auswirkungen auf die Latenz messen. * Server-Rückstand überwachen:
somaxconn
oder Serverkonfiguration bei Bedarf erhöhen. * Nachfork
Verbindungen auf der Child-Seite erneut öffnen. * DNS vorab auflösen/verwalten, wenn Sie die clientseitige Last verteilen möchten. * Messen: Client-CPU, Server-CPU, RPS, p95/p99-Latenz, Fehler/Timeouts.
Demo & Ergebnisse (Zusammenfassung)
- Naives synchrones Skript (200 gleichzeitig, 1000 Anfragen → langsamer Server): sehr hohe Client-CPU. * Dasselbe Skript mit „select“ / wait: stark reduzierte Client-CPU, Schleifeniterationen geteilt durch >100. * Drosselung beim Verbindungsaufbau hinzugefügt: weniger Timeouts und Fehler. * Vergleichstest HTTP/1 vs. HTTP/2 vs. HTTP/3: HTTP/2 bietet den besten Durchsatz auf unserem Prüfstand – HTTP/3 interessant, aber je nach Stack variabel.
Wo Sie den Code finden und fortfahren können
Der gesamte Democode und die Skripte sind auf GitHub verfügbar (mit der Präsentation verknüpftes Repository) – Sie können die Benches klonen, ausführen und die Einstellungen für Ihre Infrastruktur anpassen.
Abschluss
- Bei effektiver Netzwerkparallelität geht es nicht nur darum, mehr Verbindungen zu öffnen: Es geht darum, den Kernel für IO zu verwenden, gleichzeitige Verbindungen zu begrenzen, Ressourcen wiederzuverwenden und das Protokoll (HTTP/2/3) an den Kontext anzupassen. * Wenn Sie die Last erhöhen, beobachten Sie die Signale: Rückstand, Timeouts, Client/Server-CPU, Netzwerkfehler und passen Sie Ihre Architektur an.
Danke – wenn Sie Fragen haben, bin ich nach der Sitzung hier und der Code ist live auf GitHub.
-
API-Plattform, JsonStreamer und ESA für eine rasant wachsende API – Mathias Arlaud Hervorhebung von JSON-Streaming zur Reduzierung des Speicherverbrauchs und Steigerung der Reaktionsgeschwindigkeit von APIs im großen Maßstab.
-
Datenbankskalierung – Tobias Petry Erforschung von Datenbankskalierungsstrategien: Sharding, Replikation, Indexoptimierung. Eine Erinnerung an die zentrale Rolle der Datenbank für die Leistung.
🏗️ Feedback und Architektur
-
API-Plattform in PrestaShop, ein Kinderspiel? – Johathan Lelièvre Konkretes Feedback zur Integration der API-Plattform in eine bestehende E-Commerce-Umgebung. Herausforderungen: Kompatibilität, Leistung und schrittweise Migration.
-
API-Plattform x Redis – Clément Talleu Präsentation der Verwendung von Redis mit der API-Plattform zur Beschleunigung von Cache, Sitzungen und Job-Warteschlange.
-
Design Pattern, der Schatz liegt im Anbieter – Smaïne Milianni Ein konzeptioneller Vortrag: Wie in unseren Abhängigkeiten verborgene Muster unsere Architekturen beeinflussen und wie wir sie besser nutzen können.
-
Was wäre, wenn wir Event Storming in unseren API-Plattformprojekten verwenden würden? – Grégory Planchat Demonstration von Event Storming als kollaborative Methode zum Entwerfen umfangreicher und kohärenter Modelle.
Die Suche nach der „Wahrheit“ in verteilten Systemen
Der Vortrag von Rob Landers (Engineering Manager, Fintech) – in einen Artikel aufgenommen
TL;DR
- „Wahrheit“ in Software = beweisbare Fakten → Quelle der Wahrheit (Datenbank) + Beweis (Anwendung). * Caching beschleunigt … und führt bei schlechtem Design Lügen ein (unvollständige Schlüssel, zufällige Ungültigkeitserklärungen, Transaktionsverschmutzung, Race-to-Stale). * Externe Effekte (E-Mail, Zahlungen, Webhooks) nehmen nicht an Ihren Transaktionen teil. Lösung: Postausgang + Nachrichtenbus + Idempotenz. * Sharding vervielfacht Wahrheiten und zerstört Ihre Garantien (Transaktionen, Verknüpfungen, Migrationen). Vermeiden Sie es so weit wie möglich. * Ziel: konsistente Caches, zuverlässige Effekte, vertrauenswürdige Systeme, wenn (nicht falls) der Fehler auftritt.
Was ist „Wahrheit“ für eine Anwendung?
-
Philosophisch vage, in Software konstruieren wir es:
- Faktensammlung = Datenbank (Quelle der Wahrheit). * Nachweis dieser Fakten = Ihre Anwendung (Geschäftslogik, Invarianten). * Wenn Sie sich an dieses einfache Modell (App ↔ DB) halten können, bleiben Sie dabei.
Der unvermeidliche Cache
*Leistungsdruck → „Wir legen einen Cache an und alles wird besser.“ * Ja … bis zu dem Tag, an dem der Cache der Datenbank widerspricht und das System divergieren lässt.
Die 4 klassischen Cache-Fallen (und wie man sie vermeidet)
a) Unvollständige Schlüssel (Schlüsselkollision)
Anti-Muster
$key = "bookstore.revenue.$year"; // StoreId fehlt! return $cache->remember($key, fn() => calcRevenue($storeId, $year));
Fix: Kodieren Sie alle Abhängigkeiten im Schlüssel.
$key = "Buchhandlung.$storeId.Umsatz.$Jahr";
b) Ungültigkeitserklärungen unmöglich
- Wenn Ihr Schlüssel das Was, aber nicht das Wer/Wann kodiert, wissen Sie nicht, was Sie bei einer Änderung ungültig machen sollen. * Lösung: Tags/Gruppen. Beispiel: Taggen Sie mit
store:$id
undyear:$year
, dann ungültig machen mit Tag.
c) Transaktionale Verschmutzung
-
Sie schreiben vor „COMMIT“ in den Cache. * Wenn die Transaktion zurückgesetzt wird, sendet der Cache eine Lüge (nicht festgeschriebener Wert). * Faustregel: Schreiben/Ungültigmachen des Cache nach „COMMIT“.
- Implementieren Sie einen transaktionsbewussten Cache (Post-Commit-Hooks). * Oder verschieben Sie die „Cache-Ebene“ auf die DB-Seite (Materialisierungen/Indizes/Abfrageplan), um von den ACID-Eigenschaften zu profitieren.
d) Wettlauf zum Stillstand
-
T1 aktualisiert DB + ungültig → T2 lädt alten Wert zwischen ungültig und Commit neu → Cache veraltet. * Abhilfemaßnahmen:
- Befehl „
COMMIT
→ Ungültig machen/Schreiben“ (Post-Commit-Hooks). * Sperren/Versionen (ETags, Objektversionen) im Cache. * Kurze TTLs + robuster Cache-Aside.
- Befehl „
Cache-Checkliste > > * [ ] Schlüssel = alle Abhängigkeiten (Benutzer, Gebietsschema, Filter, Funktionsflags usw.). > * [ ] Ungültigkeitserklärungen nach Tags/Gruppen. > * [ ] Nur Cache-Schreibvorgänge nach dem Commit. > * [ ] Parallelitätstests (Race Conditions). > * [ ] Beobachtbarkeit (Treffer/Fehlschlag, Verfallsrate, Latenzen).
Externe Effekte: Wahrheit außerhalb der Transaktion
Das Problem
- Zahlungen, E-Mails, Webhooks, APIs von Drittanbietern: nicht in Ihrer Transaktion. * Irreversibler Effekt (E-Mail gesendet), unsichtbarer Zustand bis zum Commit, ungeprüfte Wiederholungsversuche.
Das Muster, das funktioniert
- Postausgang (in Ihrer DB): Schreiben Sie vor dem „Veröffentlichen“ eine Nachricht in die Datenbank in derselben Transaktion wie Ihre Geschäftsdaten. 2. Nachrichtenbus (z. B. Symfony Messenger mit Doctrine-Transport) liest den Postausgang nach dem Commit, führt den Effekt aus und markiert Erfolg/Misserfolg. 3. Idempotenzschlüssel auf der Anbieterseite (Zahlung, E-Mail): mindestens einmal → nur eine Anwendung des Effekts.
Flussdiagramm LR A[App] -- Tx begin --> DB[(DB)] A -->|Daten schreiben + Postausgang| DB DB -->|COMMIT| Q[Postausgang Reader / Messenger] Q --> S[Externer Dienst] S --> Q --> DB
Bonus
- Kompensierende Aktionen: Wir „stornieren“, indem wir fortfahren (z. B. Rückerstattung). * Idempotenz auch auf der Verbraucherseite von Webhooks (Deduplizierung per Schlüssel).
„Skalierung bis ins Unendliche“: Warum Sharding (oft) eine falsche gute Idee ist
- Keine globalen Transaktionen mehr (oder sehr teuer). * Keine Inter-Shard-Joins mehr → mühsame Denormalisierung. * Lange und riskante Migrationen (langlebiger Multi-Schema-Code). * Cache-Schlüssel müssen erweitert werden (einschließlich „shardId“). * Suche muss (neu) erfunden werden. * Nicht eindeutige Uhr (das „Jetzt“ variiert je nach Shard).
Empfehlung: Erschöpfen Sie zunächst alle vertikalen/horizontalen Aspekte ohne Sharding > (Indizes, Abfragen, Lese-Replikate, interne Partitionierung, konsistentes Caching, CQRS, Projektionen/materialisierte Ansichten). > Sharding kommt sehr weit hinten in der Kurve an.
Rezept „Zuverlässige Wahrheit“
- DB = Quelle der Wahrheit. Datenbankinvarianten, Einschränkungen, Transaktionen. 2. Cache: vollständige Abhängigkeiten, gesteuerte Ungültigkeitserklärungen, nur Post-Commit, Racetests. 3. Nebenwirkungen: Postausgang + Bus + Idempotenz (+ Kompensationen). 4. Beobachtbarkeit: Cache-Metriken (Treffer/Veraltet), Postausgangsverzögerungen, Wiederholungsraten, Warteschlangen für unzustellbare Nachrichten, Prüfpfad. 5. Belastbarkeit: Timeouts, Backoff, Leistungsschalter, Schotten. 6. Tests: Gleichzeitigkeit (Race), leichtes Chaos (Deaktivierung eines Cache-Knotens, Einfügung von Latenz). 7. Nicht sharden, solange andere Hebel vorhanden sind.
Anhang – Anti-Patterns und Abhilfemaßnahmen
if ($isAdmin) { … } if ($isCustomer) { … }
→ bevorzugeif … elseif …
, wenn exklusiv; andernfalls mache zusammengesetzte Zustände (FSM/Invarianten) explizit. * In den Cache in einer Transaktion schreiben → Schreibvorgang in einen Post-Commit-Hook oder einen Doctrine-Listener verschieben. * „Manuelle“ Ungültigkeitserklärungen → Tags/Gruppen + „Besitz“ von Schlüsseln durch begrenzten Kontext. * Bus ohne Idempotenz → deterministischer Schlüssel (z. B. Geschäfts-UUID) → mindestens einmal wird zu effektiv einmal. * Nicht deduplizierte Webhooks → Tabellewebhook_receipts(idempotency_key, received_at, status)
+ eindeutiger Index.
Abschluss
Die „Wahrheit“ wird nicht gefunden, sondern konstruiert. Indem wir klare Grenzen setzen (DB, Cache, Effekte), Zeitverpflichtungen (Post-Commit) und die Außenwelt standardmäßig als nicht vertrauenswürdig behandeln (Outbox/Idempotenz), bauen wir Systeme, die versagen, ohne zusammenzubrechen – und die auch unter Druck die Wahrheit sagen.
🛠️ Werkzeuge und Praktiken
- Composer Best Practices 2025 – Nils Adermann Aktuelle Empfehlungen für die effektive Verwaltung von Abhängigkeiten: Versionsbeschränkungen, Sicherheit, Reproduzierbarkeit von Builds.
#🧰 Composer Best Practices 2025 — von Nils Adermann
„Viele bewährte Verfahren haben sich in den letzten 5–10 Jahren nicht geändert … aber das Ökosystem, die soziale Sicherheit und unsere Tools ändern sich.“ – Nils
🆕 Was ändert sich (2025)
-
Auf Wiedersehen Composer 1 / Packagist API v1
- Upgrade auf Composer 2 (erforderlich für Updates; Composer 1 kann nicht mehr über v1 aufgelöst werden). * Wenn Sie nicht weiterkommen, können private Proxys helfen … aber der sicherste Weg bleibt die Migration.
-
Neue Bedrohungen für die Lieferkette
- Typosquatting und KI-induzierte Pakete (von Angreifern erfundene und dann veröffentlichte Namen). * Erhöhte Wachsamkeit bei dem, was Sie zu „composer.json“ hinzufügen.
-
Kleine Funktionen, die das Leben verändern
composer update --minimal-changes
: Aktualisieren Sie nur, was unbedingt nötig ist, um einen Konflikt zu lösen. *composer update --patch-only
: Nehmen Sie nur Patches (xyz) – ideal für Sicherheits-Hotfixes. *composer update --bump
(odercomposer bump
): Richtet Ihrecomposer.json
-Einschränkungen an den installierten Versionen aus. *composer audit
(wird beim Update automatisch ausgeführt): Erkennt bekannte Schwachstellen in Ihrem Schloss.
🔐 Lieferkette und Sicherheit
-
Warum alle besorgt sind. Selbst eine „kleine“ Site sammelt Daten → potenzielles Ziel (Phishing, Pivot usw.).
-
Wichtige bewährte Verfahren
-
Führen Sie „Composer Audit“ in CI aus und geben Sie eine Warnung aus, wenn nach der Bereitstellung Schwachstellen auftreten. * Fügen Sie das Metapaket „roave/security-advisories“ hinzu: Verhindert die Installation einer anfälligen Version. * Verwenden Sie ein privates Composer-Repository (Private Packagist / Nexus / Artifactory / Cloudsmith…):
- Spiegeln Sie Artefakte (nicht nur Metadaten) → schützt vor Löschung oder wildem Retagging. * Zuverlässiger Einstiegspunkt für Ihre Builds (weniger direkte Abhängigkeit von GitHub). * Versehen Sie eine veröffentlichte Version nie mit einem Retagging: Erstellen Sie eine neue Version. * Sponsoren Sie Ihre Abhängigkeiten („Composer Fund“), die PHP Foundation usw.: Es ist Ihre Lieferkette.
-
🧭 Semantik und Einschränkungen (nützliche Erinnerungen)
-
Bevorzugen Sie
^
(Caret), um „kompatibel bis zum nächsten Hauptzeichen“ auszudrücken:json { "require": { "vendor/lib": "^1.2" } } // [1.2.0, <2.0.0)
* Multi-Majors (oft für PHP):json { "require": { "php": "^8.1 || ^8.2 || ^8.3" } }
* Defekte Versionen ausschließen:json { "require": { "vendor/lib": "^1.2, !=1.3.2, !=1.4.0" } }
* Stabilität:dev
,alpha
,beta
,RC
,stable
(aus Tag abgeleitet). Branches =dev-xxx
.
🍴 Forks: temporär vs. permanent
-
Temporärer Fork (dringender Hotfix)
-
Verweisen Sie auf das VCS-Repository + Alias, damit es wie 1.2.3 aussieht:
json "repositories": [{ "type": "vcs", "url": "https://github.com/me/lib" }], "require": { "vendor/lib": "dev-fix as 1.2.3" }
* ⚠️ Sie erhalten Upstream-Updates nicht automatisch → überwachen und Upstream so schnell wie möglich zurücksetzen.
-
-
Permanente Gabel
-
Benennen Sie das Paket um (
my/lib
) und ersetzen Sie das Original:json "replace": { "vendor/lib": "self.version" }
* Veröffentlichen Sie Ihr Paket (z. B. Private Packagist) und entfernen Sie die VCS-Quelle aus dem Projekt.
-
🎯 Kontrollierte Updates
-
Teilweise:
bash composer update vendor/zebra --with-dependencies composer update vendor/zebra vendor/giraffe --with-all-dependencies
* Shockwave begrenzen:--minimal-changes
: Aktuelle Versionen nach Möglichkeit beibehalten. *--patch-only
: Nur Patches übernehmen. * Rollback blockieren:
bash composer update --bump
* Automatisieren:- Detektoren/PRs: Dependabot, Renovate (achten Sie auf Lücken); Nils stellte Conductor vor (auf PHP/Composer ausgerichtetes Tool: führt das Update in Ihrem CI aus, versteht Plugins/Skripte, gruppiert PRs besser).
🧩 Monorepos
-
Verwenden Sie „Pfad“-Repositorys, um Ihre lokalen Bibliotheken zu verknüpfen (Symlink in „vendor/“):
json "repositories": [ { "type": "path", "url": "packages/*", "options": { "symlink": true } } ]
* Ändern Sie eine Einschränkung in einer Mono-Bibliothek → führen Siecomposer update
erneut an der Wurzel aus.
🔒 Die zentrale Rolle von composer.lock
-
Lock friert den GESAMTEN Baum ein (genaue Versionen + URLs). * Commit immer
composer.lock
(für Apps). * Absichtliche Zusammenführungskonflikte (Hash) → aufmain
zurücksetzen, den genauen Aktualisierungsbefehl erneut ausführen.- Tipp: Fügen Sie den Befehl „Composer Update …“ in die PR-Commit-Nachricht ein.
🚀 Zuverlässige Bereitstellung (Pipeline-Typ)
- CI:
composer install --no-dev --prefer-dist --no-interaction --no-progress
2.composer check-platform-reqs
(oder während des Image-Builds) 3. Optimierter Autoload-Dump:composer dump-autoload -o
4. Artefakt erstellen (Docker-Archiv/Image) einschließlichvendor/
5. Artefakt bereitstellen (keine Updates in der Produktion) → überall derselbe Code, keine Überraschungen.
⚡ Caching, das funktioniert (CI)
-
Zwischenspeichern Sie den Composer-Cache (
~/.composer/cache
) und (optional)vendor/
:- Composer-Cache akkumuliert (ideal für Multi-Branch/Multi-Job). *
vendor/
umgeht die Dekomprimierung, wenn sich der Status nicht geändert hat. * Nutzen Sie in Docker Ebenen und machen Sie sie bei einer Änderung voncomposer.lock
ungültig.
- Composer-Cache akkumuliert (ideal für Multi-Branch/Multi-Job). *
📝 Checkliste „Wählen Sie 2025“
-
[ ] Composer 2 überall (+ Packagist v2 API). * [ ]
Composer-Audit
in CI + Sicherheitswarnungen außerhalb des Update-Zyklus. * [ ]roave/security-advisories
zum Blockieren anfälliger Versionen. * [ ] Privates Composer-Repo, um Artefakte zuverlässiger zu machen. * [ ] Häufige Updates (Renovate/Dependabot/Conductor), klein und regelmäßig. * [ ]--minimal-changes
,--patch-only
,--bump
in Ihrer Routine. * [ ] Commitcomposer.lock
und Dokumentaktualisierungsbefehle. * [ ] Composer-Cache-Caching (+vendor/
je nach Kontext). * [ ] Nicht neu taggen; eine neue Version veröffentlichen. * [ ] Unterstützen Sie Ihre Abhängigkeiten (Composer Fund
). -
Erweitern des Caddy-Webservers mit Ihrer bevorzugten Sprache – Sylvain Combraque Präsentation der Erweiterungsmöglichkeiten von Caddy, um benutzerdefinierte Funktionen direkt in den Server zu integrieren.
-
Den PHP-Kern erweitern – Test für Test – Florian Engelhardt Ein Plädoyer, durch gezielte Unit-Tests zur Sprache beizutragen. Jeder Test zählt, um PHP zu stärken.
Hier ist eine klare, vortragsfertige Version von Florians (FR) Vortrag mit einer Handlung, die sich an das hält, was er sagt, synthetisierten „Demo“-Passagen und einprägsamen Pointen.
Werden Sie PHP-Mitwirkender … indem Sie Tests schreiben
(und ein bisschen Geschichte von 1993 bis heute)
👋 Einführung
Hallo, mein Name ist Florian. Ich arbeite im Profiler-Team bei Datadog, wo ich einen kontinuierlichen Profiler für PHP entwickle. Außerdem trage ich zu Open Source bei: PHP-Core, PHPUnit, GraphQLite … und bin Mitbetreuer der parallelen Erweiterung (Multithreading in PHP). Und das alles mache ich … während ich verheiratet bin und fünf Kinder habe. Kurz gesagt: Ein bisschen Zeit zum Mitmachen findet man immer 😉
🧒 Persönliche Vorgeschichte
- 1993: erster PC (IBM PS/2, 286) + ein Buch „GW-Basic für absolute Anfänger“ → erste Schritte im Programmieren. * 1995: Ich entdecke das Internet, HTML/CSS/JS/Perl. Wir deployen per FTP + F5. * 2000: Ich trete einer Webagentur in Deutschland bei. Zwei Teams: JSP und PHP. Ich werde auf die PHP-Seite gesetzt. Mir wird
echo 1+1
→ F5 → 2 gezeigt. Ich antworte: „Das wird nie jemand benutzen.“ 😅 Dann werden mir MySQL, echter Code, echte Projekte gezeigt … und ich verstehe endlich, was ein Softwareentwickler den ganzen Tag macht.
🧭 Warum dieses Gespräch
In meiner 25-jährigen Karriere hat mir PHP alles gegeben. Ich wollte der Community etwas zurückgeben, ohne jedoch mit dem Schreiben von C oder einem RFC anzufangen. Ich entdeckte das PHP TestFest (Ausgabe 2017): Die Idee ist einfach: Tests für PHP schreiben. Perfekt, um die Codebasis zu lernen und sofort mitzuwirken.
🔧 PHP erstellen und die Testsuite ausführen
Aus der Quelle kompilieren
git clone https://github.com/php/php-src.git cd php-src ./buildconf ./configure make -j$(nproc) sapi/cli/php -v # prüft: PHP 8.x-dev
Führen Sie die Tests (parallel) aus.
# Aus dem Repo-Stammverzeichnis make test # sequential # oder php run-tests.php -j10
- Über 18.000 Tests, Bestehen/Überspringen/Nichtbestehen klar aufgelistet. * Viele Überspringungen, wenn Erweiterungen nicht kompiliert werden. * Abschlussbericht mit Statistiken und möglichen Nichtbestehen (wird untersucht).
🧪 PHPT: das PHP-Testformat
Ein Test ist eine .phpt
-Datei in Abschnitten:
--TEST--
Kurztitel (+--DESCRIPTION--
falls erforderlich) *--EXTENSIONS--
Abhängigkeiten (z. B.zlib
) *--SKIPIF--
Sprunglogik (Betriebssystem, Netzwerk usw.) *--FILE--
getesteter PHP-Code (oftvar_dump
) *--EXPECT--
erwartete Ausgabe *--CLEAN--
Housekeeping (isoliert von--FILE--
)
Tipps: Jeder Abschnitt wird isoliert ausgeführt → keine gemeinsam genutzten Variablen.
🧩 Echtes Beispiel: Testen von zlib_get_coding_type()
Kontext
-
PHP kann die Ausgabe automatisch komprimieren, wenn
zlib.output_compression=On
ist und der ClientAccept-Encoding
sendet. * Die Funktionzlib_get_coding_type()
gibt zurück:false
, wenn keine Komprimierung erfolgt, *"gzip"
/"deflate"
, abhängig vom Algorithmus, den PHP verwendet.
Fallideen zum Testen
- Kein
Accept-Encoding
→false
2.Accept-Encoding: gzip
+ Komprimierung aus →false
3.Accept-Encoding: gzip
+ Komprimierung an →"gzip"
Die aufgetretenen Fallstricke (und was sie gelernt haben)
-
Header bereits gesendet
-
Wenn Sie etwas drucken, bevor Sie die INI ändern, sendet PHP die Header → Sie können die Komprimierung nicht mehr ändern. * Lösung: Puffern Sie die Ausgabe (in einer Variable speichern, nicht zu früh „echoen“). 2. Copy-on-Write-Superglobale
-
Das Ändern von
$_SERVER['HTTP_ACCEPT_ENCODING']
in Userland ändert nicht den internen Wert, der von der Engine verwendet wird. * Lösung: Verwenden Sie den Abschnitt--ENV--
von.phpt
, umHTTP_ACCEPT_ENCODING=gzip
zu Beginn des Testprozesses einzufügen. 3. Seien Sie vorsichtig mit der Ausgabe -
Bei aktivierter Komprimierung wird die Ausgabe zu ... gzip-Binärdateien. * Lösung: Erfassen Sie, ändern Sie die INI und geben Sie dann die erwartete Ausgabe aus, löschen Sie sie für „--EXPECT--“.
-
Ergebnis: Robuster Abschlusstest, integriert (damals PHP 7.3) und Abdeckung auf ungetesteten Zweigen erreicht.
🎁 Was ich auf dem Weg gelernt habe
- Superglobals (
$_SERVER
,$_GET
,$_POST
…) sind Copy-on-Write → das interne Original bleibt unveränderlich. *ini_set()
ist keine „Magie“: Nach dem Senden der Header ist es manchmal zu spät, ein Verhalten zu ändern, das in der HTTP-Antwort hätte deklariert werden sollen. * Es gibt verborgene Schätze: Beim Durchsuchen des Covers habe ich ZipArchive usw. (wieder)entdeckt. * Das PHPT-Format ist nicht dem Kernel vorbehalten: PHPUnit weiß auch, wie man sie ausführt – nützlich zum Testen einer SAPI/CLI oder einer Binärdatei.
🚀 Warum Sie Tests für PHP schreiben sollten
- Sie stabilisieren das Ökosystem für alle. * Sie lernen den Schrittmotor, ohne eine einzige Zeile C zu schreiben. * Sie werden … ein PHP-Mitwirkender (und das ist cool ✨).
Wo soll ich anfangen (5-Minuten-Checkliste)
- Fork
php-src
,buildconf && configure && make
. 2.php run-tests.php -j8
für einen ersten Lauf. 3. Codecov/coverage öffnen → einfaches Rot suchen (Switch/Return). 4. 1.phpt
schreiben:--ENV--
,--EXTENSIONS--
,--FILE--
,--EXPECT--
. 5.make test TESTS=Pfad/zu/Ihrem-Test.phpt
. 6. Kleine, gezielte PR, klare Erklärungen → einfacheres Zusammenführen.
🧑💻 Schlusswort
Wir tun das nicht, weil es einfach ist, sondern weil wir denken, dass es einfach sein wird ... und wir lernen dabei. Vielen Dank – und wenn Sie Fragen haben, bin ich für Sie da!
- MongoDB: Fordern Sie mehr von Ihrer Datenbank – Jérôme Tamarelle Übersicht über die erweiterten Funktionen von MongoDB (Aggregationen, komplexe Abfragen) in einem API-Kontext.
🧑💻 FrankenPHP im Rampenlicht
-
Wie Clever Cloud seine Art der Bereitstellung von PHP-Anwendungen mit FrankenPHP neu gestaltet hat – Steven Le Roux & David Legrand Feedback zur Integration von FrankenPHP in ein PaaS. Steigerung von Effizienz, Einfachheit und Leistung.
-
FrankenPHP in der Produktion, Migration einer E-Commerce-Site – Loïc Caillieux Praxisbeispiel zur Migration eines Projekts zu FrankenPHP. Leistungsdaten und Feedback zur Stabilität.
💡 Weitere bemerkenswerte Vorträge
-
Mercure, SSE, API-Plattform und ein LLM erstellen einen Chat(bot) – Mathieu Santostefano Experimentieren mit einem Echtzeit-Chatbot mit Mercure und API-Plattform, angereichert durch einen LLM.
-
Wie API Platform 4.2 die API-Entwicklung neu definiert – Antoine Bluchet (Soyuka) Detaillierte Präsentation der neuen Funktionen in 4.2: neue Filter, DX-Verbesserungen, bessere Skalierbarkeit.
Großartig, hier ist der schriftliche Bericht von Antoine Bluchet (Soyuka) Vortrag – „API-Plattform 4.2“.
🎉 10 Jahre API-Plattform & Veröffentlichung von 4.2 (live auf der Bühne)
„Die Pressemitteilung erscheint direkt nach dem Vortrag – das WLAN spielt mir Streiche.“ – Antoine
🚦 Retro 4.0 → 4.2
- 600 Commits, 200.000 Zeilen geändert; 300 Probleme geöffnet, von denen 2/3 geschlossen sind. * Danke an Les-Tilleuls.coop für das Vollzeit-Sponsoring von Antoine.
🧩 Metadaten: Einfacher deklarieren und ändern
- Neue PHP-Deklaration (zusätzlich zu Attributen/YAML), portiert von Symfony. * Gezielte Mutatoren:
AsResourceMutator
/AsOperationMutator
(+OperationMutator
-Schnittstelle), um eine Operation/Ressource ohne Aufwand anzupassen (nützlich für das Serious Bundle).
🔎 Filter, endlich entkoppelt (Dokument ↔ Transformation ↔ Validierung ↔ SQL)
Historisch gesehen war ein Filter eine gemischte Beschreibung, eine SQL-Strategie usw. In 4.2 trennen wir die Verantwortlichkeiten:
-
Dokumentation:
-
JsonSchemaFilterInterface
— deklariert das Schema eines Parameters (abgeleiteter Typ → automatische Zwang/Validierung auf PHP-Seite). *OpenApiParameterFilterInterface
— OpenAPI-Parameter (können JSON-Schema überschreiben). * Filterung: unveränderte Speicherschnittstellen (ORM/ODM/ES…). -
Filter werden zu einfachen Rückrufen ohne DI, die typisierte Parameter empfangen.
-
🧭 Einheitliche HTTP-Parameter
- Neue Attribute „Parameter“ (Abfrage) und „HeaderParameter“ (Header) mit erweiterten Optionen (Typ, Array, Formate, Zwangskonvertierung usw.). * Parameter werden unabhängig von Entitätseigenschaften für die Operation deklariert. * Freitextabfrage „q=“ (Hydra-Stil) sofort einsatzbereit. * Zusammengesetzte Filter möglich, wodurch sehr alte historische Tickets geschlossen werden.
🔗 „Intelligente“ Pfadparameter
- „Link erweitert Parameter“ + dedizierter Anbieter zum Auflösen einer verknüpften Ressource (z. B. „Unternehmen“, das als gebrauchsfertige Entität in den Anbieter eingefügt wird).
📜 OpenAPI & JSON-Schema: leichter, sauberer
- Schema-Pooling: ein Basisschema + Anreicherungen (JSON-LD, JSON-API, …) durch $ref → −30 % Größe bei großen Spezifikationen, weniger E/A. * ⚠️ Wenn Sie die genaue Form der Schemata getestet haben, erwarten Sie Unterschiede (die funktionale Validierung bleibt gleich). * Neuer, strengerer/aktualisierter Validator; viele Inkonsistenzen behoben.
⚡ Leistung: FrankenPHP im Worker-Modus, Zahlen zur Unterstützung
- NGINX/PHP-FPM vs. FrankenPHP Bench (optimierte „Sweet Spot“-Konfiguration). * Ohne Worker: gleichwertig. Mit Worker: +RPS, Latenz ÷2 auf der Sylius-Seite. * Kernbotschaft: Worker-Modus aktivieren. (Und ärgern Sie diejenigen, die es noch nicht getan haben 😉)
🧱 Statusoptionen: Links und Unterressourcen … schmerzlos
-
Für bestimmte Unterressourcen gibt ein dedizierter Rückruf ein klares „WO“ und vermeidet große automatische Diagramme. * Entity-Class-Magie modernisiert mit Symfony ObjectMapper:
- Ihre Shape-API muss nicht mehr mit der Doctrine-Entität übereinstimmen. * Wir kommentieren mit
#[Map]
, um Entsprechungen zu beschreiben (z. B.Vorname
+Nachname
→Benutzername
). * Sauberes und wartungsfreundliches bidirektionales Mapping.
- Ihre Shape-API muss nicht mehr mit der Doctrine-Entität übereinstimmen. * Wir kommentieren mit
🛒 Realer Fall (Sylius + JSON-LD / schema.org)
- Stellen Sie ein schema.org-kompatibles Produktblatt in JSON-LD bereit, obwohl die Sylius-Entität nicht übereinstimmt. * Provider, der Sylius liest → ObjectMapper, der neu zuordnet → Serializer, der das JSON-LD ausgibt. * Kehren Sie vom API-Plattform-Profiler (Inhaltsverhandlung, Provider, Serializer usw.) zurück, um zu sehen, wo die Zeit bleibt (häufig Serialisierung).
🧵 Integrierter JSON-Streamer: Serialisieren Sie große Nutzlasten schneller
-
Integration des Symfony JSON Streamers (+ TypeInfo) für JSON und JSON-LD. * Prinzip: vorberechnetes Schema, Zeichen-für-Zeichen-Streaming. * Gemessene Gewinne: bis zu +32 % RPS in Antoines Tests (je größer das Objekt, desto mehr Gewinn). * Aktivierung: Tool-Option
json_stream: true
.- ⚠️ Erfordert öffentliche Eigenschaften (ansonsten bleiben Sie beim klassischen Serializer). * Weitere Informationen: dedizierter Vortrag von Mathias Arlaud.
🧡 Laravel: Funktionale Abdeckung im Boom
- Seit der Einführung im letzten Jahr: 124 PRs und 100 Probleme behoben. * 80–90 % der API-Plattformfunktionen sind jetzt auf der Laravel-Seite einsatzbereit (einschließlich HTTP-Cache). * Danke an die wichtigsten Laravel-Mitwirkenden. Und die Bereitstellung in der Laravel Cloud, präsentiert von Joe Dixon.
🧪 Verfügbarkeit und Kompatibilität
- 4.2: Direkt nach dem Vortrag veröffentlicht (Beta vorhanden). * Wichtigste Änderung: JSON-Schemaformat (nicht Substanz). * OpenAPI-Standards angepasst (geringes Risiko von Auswirkungen). * Parameter: Nicht mehr experimentell – übernehmen Sie sie.
🛣️ Roadmap zu 5.0
#[ApiFilter]
zugunsten des Einstellungssystems verwerfen (unterstützte Migration: Skript und Kompatibilität lange Zeit beibehalten). * JSON-Streamer auf andere Formate erweitern; Feedback und Tests sind willkommen. * ObjectMapper (Symfony) durch konkrete Anwendungen im Ökosystem weiterentwickeln.
✋ Wichtige Punkte (TL;DR-Version)
- Einheitliche Parameter (typisiert, dokumentiert) + entkoppelte Filter ⇒ DX und Präzision. * OpenAPI leichter und strenger. * FrankenPHP (Worker) ⇒ echte Leistungssteigerung. * ObjectMapper ⇒ Saubere API, auch wenn Ihre Entitäten es nicht sind. * JSON Streamer ⇒ schnellere große Nutzlasten. * Laravel: das ist es, wir sind (fast) Feature für Feature da.
Möchten Sie, dass ich eine Checkliste für die Migration von 4.1 nach 4.2 (Parameter, Schemata, Leistung) + Beispiele für Anmerkungen erstelle, die zum Kopieren und Einfügen bereitstehen?
- Wie Laravel Cloud FrankenPHP in der Produktion verwendet – Florian Beer Konzentrieren Sie sich auf die Synergie zwischen Laravel Cloud und FrankenPHP.
🚀 Kontext
Florian Beer (Laravel Cloud-Infrastrukturteam) erklärte, wie die im Februar eingeführte Zero-Ops-Plattform es ermöglicht, eine Laravel-App „in einer Minute“ bereitzustellen (GitHub/GitLab/Bitbucket-Verbindung → Deploy → öffentliche URL). Das Ziel: kein clientseitiges Infrastrukturmanagement (Server, Container, Skalierung, Netzwerk … alles wird verwaltet).
⚙️ Octane, die langlebige Ausführung
- Ohne Octane: Laravel läuft auf PHP-FPM, die Anwendung bootet bei jeder Anfrage. * Mit Octane: Die App bootet einmal und bleibt im Speicher; Anfragen werden von einem lang laufenden Worker bearbeitet. * Octane unterstützt mehrere Server; Laravel Cloud hat sich für FrankenPHP entschieden.
🧩 Warum FrankenPHP?
FrankenPHP (basierend auf Caddy) bietet:
- HTTP/2 & HTTP/3, Early Hints, Auto TLS, * ein leistungsstarker Worker-Modus, * einfache Integration in das Laravel/Octane-Ökosystem.
In der Praxis auf Laravel Cloud Octane aktivieren = zu FrankenPHP wechseln (und ggf. zu PHP-FPM zurückkehren).
🎬 Live-Demo (Schritt für Schritt)
- Erstellen Sie eine App über eine Vorlage in der Laravel Cloud (Region Frankfurt). 2. Erstmaliges Deployment → App in PHP-FPM zugänglich. 3.
composer require laravel/octane
, fügen Sie eine „Runtime“-Route hinzu, um Laufzeitinformationen verfügbar zu machen. 4. Pushen → Auto-Deploy (Container erstellen, veröffentlichen). 5. Betätigen Sie den Schalter: Aktivieren Sie Octane in der Benutzeroberfläche → Erneutes Deployment. 6. Die „Runtime“-Route zeigt jetzt FrankenPHP als Laufzeit.
💡 Warnung: Achten Sie im Worker-Modus auf Speicherlecks im Anwendungscode (Kundenverantwortung). Die Plattform erleichtert die Aktivierung, führt jedoch keine „Garbage Collect“-Operation für Ihre Geschäftslogik durch.
🏗️ Unter der Haube von Laravel Cloud
-
Die Plattform verwaltet zwei Familien von Docker-Images:
- PHP-FPM (klassisch), * FrankenPHP (Octane). * Die Pipeline nimmt Ihr Repo, erstellt das Image, überträgt es und verbindet den Dienst mit dem öffentlichen Netzwerk.
🤝 Leistung & Zusammenarbeit
- Direkte Zusammenarbeit mit Kévin Dunglas zur Optimierung von FrankenPHP für eine Vielzahl von Workloads (von Nebenprojekten bis hin zu SaaS mit hohem Datenverkehr). * Ergebnis: Auf der Clientseite wurden bereits erhebliche Leistungssteigerungen beobachtet.
✅ Probleme und bewährte Methoden
-
Wann sollte ich zu Octane/FrankenPHP wechseln?
-
Intensive E/A, kritische Latenz, heiße Endpunkte, ausgelastetes Web/API. * Wichtige Punkte:
-
Globaler Status und Singletons (zwischen Anfragen gut neu initialisiert), * Verbindungen (DB, Cache) werden im Lebenszyklus des Workers ordnungsgemäß verwaltet, * Beobachtbarkeit (Metriken, Speichernutzung pro Worker).
-
🧭 Kernbotschaft
In Laravel Cloud werden Octane + FrankenPHP mit einem Klick aktiviert. > Sie behalten die Einfachheit von Zero-Ops bei und nutzen gleichzeitig die Vorteile der modernen Laufzeit und des Worker-Modus für mehr Leistung.
- Hilfe! Meine technischen Fähigkeiten haben ein Verfallsdatum – Helvira Goma Überlegungen zur schnellen Veralterung von Fähigkeiten und wie man in einer sich ständig verändernden Branche relevant bleibt.
🎤 Tag 2 – 19. September
🔑 Keynotes
- Nicolas Grekas: Status, neue Funktionen und Roadmap von Symfony. * Fabien Potencier: Langzeitvision von Symfony und Fokus auf KI-bezogene Komponenten.
Hier ist eine vortragsfertige Version (mit Folientiteln) von Fabien Potenciers Vortrag zum Thema „LLMs, Agenten und die Zukunft von APIs“. Ich habe den pragmatischen Ton und die konkreten Beispiele beibehalten.
#1) Warum dieses Gespräch?
- Die Welt der KI entwickelt sich so schnell, dass das, was ich heute sage, morgen schon überholt sein kann. * Ziel: Verstehen, wie LLMs und Agenten die Art und Weise verändern, wie wir APIs entwerfen.
Wer hier verwendet (fast) täglich ein LLM zum Programmieren? Wer hat noch nie eine API aufgerufen? Probier es aus 😉
#2) Was ist ein „Agent“?
- Definition (anthropisch, zusammengefasst): Ein Modell, das Werkzeuge in einer Schleife verwendet. * Mentales Schema: Eingabeaufforderung → wählt ein Werkzeug → beobachtet → wiederholt → erzeugt ein Ergebnis. * Mögliche Werkzeuge: Webbrowser, SDK/API, lokal ausführbare Datei, selbst erstellte Funktion … * Wichtig: Sowohl „Mensch“ als auch „Maschine“: plant, hat ein Gedächtnis, ergreift die Initiative, bleibt aber ein Programm.
#3) 30 Jahre Schnittstellen: von der Website zum Agenten
-
90er: Websites für Menschen (reines HTML, dann CSS/JS). * CLI: für Entwickler/Ops. * APIs: Maschine-zu-Maschine (Mashups!), intern oder öffentlich, mit der Erwartung von Vollständigkeit und Determinismus. * Neu: Agenten interagieren mit allem:
- Websites (Scraping-/Browsing-Tool), * CLI (über MCP-Server), * APIs (über SDKs oder direktes HTTP).
#4) Aktuelle APIs: Perfekt für Programme, nicht für Agenten
- Strenge Ein-/Ausgaben (OpenAPI/JSON), Fehler über HTTP-Status (400, 422, 429 usw.). * Für deterministische Apps ist dies ideal: Im Fehlerfall korrigiert ein Mensch den Code. * Ein Agent muss sich jedoch selbst wiederherstellen: Er benötigt Aktionsmöglichkeiten, nicht nur „400 Bad Request“.
#5) Wenn ein Agent auf Ihre Fehler stößt
- 400 / 422 / 429: Der Agent sieht den Code … und rät (manchmal falsch): Fehlendes Feld? Falsches Format? Später noch einmal versuchen? * Fehlerhafte Schleife: Er versucht es, schlägt fehl, googelt, liest das Dokument erneut, versucht es erneut … → langsam, teuer, nicht deterministisch. * Schlimmer noch: Viele SDKs (z. B. in Python) geben nur den Standardstatuscode zurück → der detaillierte Fehlertext geht verloren.
#6) Fehler machen… Aktionstipps
-
In der Antwort (nicht nur im Code):
- Problemtitel + umsetzbares Detail, * Link zu einer bestimmten Seite (nicht zum Stammdokument), * konkreter Vorschlag: „Das Feld „Datum“ muss im Format „JJJJ-MM-TT“ sein“, „Menge“ ≤ 100, „Dieser Endpunkt ist veraltet, verwenden Sie „/orgs/{id}/projects“. * Vorteile: weniger Iterationen, weniger Token, weniger Kosten, weniger Halluzinationen.
Symfony unterstützt seit langem die Fehlerstrukturierung (JSON-Problem): Nutzen Sie dies, um Ihre Fehlernutzlasten zu standardisieren.
#7) Konsistenz > Intelligenz
-
LLMs lieben Vorhersehbarkeit: Wählen Sie einen Stil und bleiben Sie dabei.
user_id
überall (nichtuserId
hier undauthor_id
anderswo). * Felder, URL-Namen, Formate: Konsistenz. * Andernfalls „rät“ der Agent … und macht einen Fehler.
#8) „AX“-Dokumentation (eXperience Agent)
-
Einheitlich, aktuell, zentralisiert: Vermeiden Sie veraltete Seiten und gefälschte Beispiele (LLMs kopieren sie). * Tracks:
- LLMS.txt (Inventar für LLMs), * jede Seite in Markdown sichtbar (LLMs lesen MD sehr gut), * Pfadanleitungen (z. B. „Produkt kaufen“: Authentifizierung → Warenkorb → Adresse → Zahlung), * mögliche Fehler pro Endpunkt dokumentieren, wie sie behoben werden können, und korrekte Beispiele bereitstellen.
Ein schlechtes Beispiel im Kontext kann die Antworten eines LLM stundenlang „verunreinigen“.
#9) Minimieren Sie den Austausch mit dem Agenten
- Ein API-Aufruf: 10–100 ms; ein LLM-Aufruf: Sekunden. * Weniger Runden = schneller, günstiger, stabiler. * Idee: Stellen Sie zusätzlich zu Ihren Low-Level-Endpunkten einige aufgabenorientierte High-Level-Endpunkte bereit („Checkout“, „Vollständiger Export“, „Projekt bereitstellen“), um 5 Aufrufe zu vermeiden, wenn 1 ausreicht.
#10) Testen… des Indeterministischen
-
Agenten sind nicht deterministisch. Dennoch sind Tests erforderlich:
- niedrige Temperatur, Wiederholungslimits, eingeschränktere Eingabeaufforderungen, * Metriken (Erfolgsrate, Latenz, Kosten) und Dashboards, * Akzeptieren des „Grauen“ (ausreichend gute Szenarien).
#11) Tokens: Wo die Rechnung schmerzt
-
Die Abrechnung erfolgt pro Token (nicht pro Charakter). * Überraschende Auswirkungen:
- Englische Kurzwörter = 1 Token; Französisch/Akzente/Unicode = oft mehrere; * Zufällige UUIDs und IDs → tokenisiert sehr teuer; *
category_id
kann je nach Tokenisierer 1 Token sein,DoneAt
vsCompletedAt
macht nicht immer einen Unterschied. * Ausführliches JSON ist teuer; strukturiertes Markdown ist für das Modell oft „lesbarer“ und weniger tokenisiert. * Langer Kontext ≠ Präzision: Je größer der Kontext, desto mehr wird der Agent verwirrt. Segmentieren Sie, was Sie Agenten zur Verfügung stellen (MCP, Sub-APIs).
- Englische Kurzwörter = 1 Token; Französisch/Akzente/Unicode = oft mehrere; * Zufällige UUIDs und IDs → tokenisiert sehr teuer; *
#12) Anmeldeinformationen und Sicherheit: Lassen Sie den Agenten nicht mit dem Feuer spielen
- Geben Sie niemals Geheimnisse in einer Eingabeaufforderung an. * Verwenden Sie vorzugsweise einen Proxy mit Tools (z. B. einen MCP-Server), der die Schlüssel verwaltet, die Anrufe tätigt und die Berechtigungen einschränkt. * Geben Sie dem Agenten Token mit begrenztem Gültigkeitsbereich (schreibgeschützt, minimaler Gültigkeitsbereich). * Fall 429 (Ratenbegrenzung): Geben Sie an, was zu tun ist („Wiederholen nach: 3“, empfohlene Verzögerung, Kontingent pro Minute usw.).
#13) Einige „Rezepte“, die Sie morgen anwenden können
- Umsetzbare Fehler + spezifische Links; Status/Text standardisieren. * Veraltet: In der Antwort UND im Dokument melden; Alternative vorschlagen. * Makro-Endpunkte (Aufgaben) zusätzlich zu Mikro-Endpunkten. * Einheitliche Namen und Formate. * Zentrales Dokument in Markdown, indiziert (LLMS.txt). * JSON-Ausführlichkeit begrenzen, gigantische IDs vermeiden; paginieren. * Integrieren Sie einen MCP-Server, um Ihre Tools/SDKs Agenten ordnungsgemäß zugänglich zu machen.
#14) Von DX/UX zu AX (Agent eXperience)
Wir haben große Fortschritte bei DX und UX gemacht. Der nächste Schritt ist AX: die Entwicklung verständlicher, umsetzbarer und vorhersehbarer APIs für Kunden … die denken.
Was Sie für Agenten tun, kommt auch den Menschen zugute: weniger Fehler, bessere Dokumentation, weniger Reibung.
Abschluss
- Agenten nutzen Ihre APIs bereits. * Helfen Sie ihnen: weniger Hin und Her, Fehler als Leitfaden, Konsistenz, brauchbare Dokumentation, kontrollierte Sicherheit. * Die Zukunft der APIs ist nicht nur Maschine↔Maschine: Es ist eine Maschine, die denkt ↔ ein gut konzipierter Service.
Danke 🙏 – Fragen sind willkommen!
🏗️ Architektur und REX
-
2025, eine API-Plattform-Odyssee – James Seconde Ein Überblick über die vergangenen und zukünftigen Entwicklungen der API-Plattform.
-
Bereitstellen der API-Plattform auf Laravel Cloud – Joe Dixon Konkretes Beispiel für die Integration und Bereitstellung einer API-Plattform in einer Laravel Cloud-Plattform.
-
Headless & Skalierbar: Entwerfen einer entkoppelten Anwendung mit API-Plattform und Vue.js – Nathan de Pachtere Demonstration eines Headless-Projekts mit API-Plattform als Backend und Vue.js als Frontend.
-
Eine nahtlose Multi-Tenant-API mit API Platform, Symfony und PostgreSQL – Mehdi Zaidi Technische Strategien für die Verwaltung mehrerer Clients auf einer einzigen API-Instanz unter Nutzung von PostgreSQL.
🛠️ Tools und Best Practices
-
Machen Sie Ihre Front-End-Entwickler mit RFC 7807 glücklich – Clement Herreman So normalisieren Sie API-Fehler mit RFC 7807 für eine bessere Front-End-DX.
-
Symfony und Dependency Injection: Von der Vergangenheit in die Zukunft – Imen Ezzine Eine Geschichte und Prognose zur Entwicklung der Dependency Injection in Symfony.
-
Typsystem und Subtypisierung in PHP – Gina Peter Banyard Theoretische und praktische Darstellung des Typsystems in PHP aus akademischer Perspektive.
-
PIE: The Next Big Thing – Alexandre Daubois Ein Blick auf einen neuen technologischen Vorschlag, der unsere Arbeitsweise mit PHP verändern könnte.
Pi: das Tool, das PHP und seine Erweiterungen in Einklang bringt
Auf dem Weg zu einem „Composer für Erweiterungen“, unterstützt von der PHP Foundation
TL;DR
Installieren, aktualisieren und deinstallieren Sie PHP-Erweiterungen mühelos – mit Abhängigkeitsmanagement, Signaturen, PHP-Versionserkennung, composer.json-Integration und mehr. Pi bietet genau das. Entwickelt und finanziert von der PHP Foundation, nutzt Pi das Packagist-Ökosystem für Metadaten, automatisiert die php.ini-Bearbeitung, unterstützt privates GitHub, Windows, Linux und macOS – und soll die herkömmliche PECL/Pickle-Nutzung ersetzen.
Warum ein neues Tool für Erweiterungen?
In unseren Projekten ist die Installation einer PHP-Bibliothek trivial („composer require …“). Andererseits reimt sich die Installation einer Erweiterung (Redis, MongoDB, Xdebug, PCOV usw.) oft mit:
- Systemabhängigkeiten, „./configure && make && make install“, * Variationen durch OS/ABI/PHP-Versionen, * manuelle Bearbeitung von INI-Dateien, * fragile Konsistenz zwischen CI/Dev/Prod-Umgebungen.
Es gibt Initiativen, die versucht haben, diese Reibung zu glätten (PECL/Pickle, Docker PHP Extension Installer), allerdings mit Einschränkungen: langsame und schwer zu wartende Site, Fehlen verallgemeinerter Signaturen, unvollständige Erkennung von PHP-Kompatibilitäten, enge Kopplung an Docker usw.
Aus dieser Beobachtung heraus entstand Pi: die Erfahrung eines Komponisten in Erweiterungen einzubringen.
Pi in zwei Sätzen
- Was es ist: Ein Erweiterungsmanager, der Ihre PHP-Erweiterungen automatisch herunterlädt, erstellt (oder bei Bedarf Binärdateien abruft), installiert und aktiviert. * Was es ändert: Sie behandeln Ihre Erweiterungen als Projektabhängigkeiten (Packagist-Metadaten, Versionsbeschränkungen, composer.json-Integration), aber mit der für die Erweiterungswelt erforderlichen Intelligenz (C/Rust/Go, Kompilierung, DLL/SO, ABI usw.).
Hauptmerkmale
-
Vereinfachte Installation
# Lokale zwischengespeicherte Quellen herunterladen pi download redis # Erstellen (konfigurieren/kompilieren) Sie entsprechend Ihrer Plattform pi build redis # Alles in einem: Download + Build + Installation + Aktivierung pi install redis ```
-
Automatische Aktualisierung von „php.ini“. Sie müssen „extension=…“ nicht manuell hinzufügen: Pi aktiviert die Erweiterung in der richtigen Konfiguration.
-
Intelligente Kompatibilität (PHP/OS/arch) Erweiterungsautoren können die Betriebssystemkompatibilität einschränken und PHP-Mindest-/Maximalgrenzen festlegen; Pi blockiert alles, was nicht übereinstimmt.
-
Signaturen und Überprüfungen Pi weiß, wie signierte Artefakte (z. B. GitHub-Releases) verwendet und die Integrität vor der Installation überprüft werden.
-
Privat und Monorepo-freundlich. Fügen Sie Repositories wie Composer: VCS, lokaler Pfad, Private Packagist usw. hinzu – ideal für private Erweiterungen.
bash pi repo add my-ext vcs https://github.com/acme/php-ext-foo.git
-
Lesen von
composer.json
. Ein einfachespi install
in Ihrem Projekt ermöglicht es Pi, Ihrcomposer.json
zu scannen (z. B.require: { "ext-redis": "*" }
) und fehlende Erweiterungen zu installieren. 🪄 -
Saubere Deinstallation
bash pi deinstallieren xdebug
-
Multi-PHP-Unterstützung. Installation für eine bestimmte PHP-Binärdatei (nützlich bei Multi-Die-CI):
bash pi install pcov --with-php-path=/usr/bin/php8.3
-
Windows First-Class: Unter Windows ruft Pi vorkompilierte DLLs ab, sofern verfügbar; unter Linux/macOS kompiliert Pi standardmäßig (klassisch und zuverlässig).
-
Symfony CLI-Integration Normale Benutzer können Pi steuern über:
„bash symfony pi install xdebug“
Wo sind die Erweiterungspakete?
Pi nutzt Packagist zur Indexierung von Metadaten (Name, Version, PHP/OS-Einschränkungen, Quellen, Signaturen usw.). Pi-kompatible Erweiterungen werden über einen dedizierten Anbieter (z. B. „packagist.org/extensions/…“) oder über eigene Repositories veröffentlicht. 👉 Konsequenz: Gleiche Reflexe wie Composer (semantische Versionierung, Bereiche, private Repositories).
Typischer Arbeitsablauf (Entwickler & CI)
-
Deklarieren Sie Ihre Anforderungen (in der README und/oder über
composer.json
:ext-…
). 2. Entwicklerbash pi install # installiert alle vom Projekt angeforderten Erweiterungen php -m | grep redis
3. CI- Cachen Sie Pi-Cache und erstellen Sie Artefakte für mehr Geschwindigkeit. * OS × PHP-Matrix: Pi verarbeitet Build- und Aktivierungsunterschiede. * Vermeiden Sie pipelinespezifisches „apt-get“/„brew“: Pi zentralisiert.
Schnelle Vergleiche
| Benötigt | PECL/Pickle | Docker Ext Installer | Pi | | ------------------------------- | ----------- | -------------------- | -------------------------------- | | Lokale Installation ohne Docker | Mittel | Nein | Ja | | PHP/OS-Versionserkennung | Teilweise | N/A (Docker) | Ja (Metadaten) | | Signaturen und Verifizierung | Heterogen | N/A | Ja | | Automatische Aktivierung (php.ini
) | Nein | N/A | Ja | | Private Repositories | Kompliziert | Nein | Ja (VCS, Private Packagist) | | composer.json
lesen | Nein | Nein | Ja | | Windows | Variable | Nein | Ja (DLL) |
Express-FAQ
Gibt es ein .lock
pro Projekt wie bei Composer? Nein. Eine Erweiterung wird auf System-/PHP-Binärebene installiert. Pi verfolgt, was es verarbeitet (pi show
) und berücksichtigt die Ziel-PHP-Version (--with-php-path
). Die Reproduzierbarkeit erfolgt auf CI-Ebene (Matrix/Betriebssystem/Versionen) und über Ihre Einschränkungen.
Kann ich Pi mit privaten GitHub-Quellen verwenden? Ja: Pi liest „GH_TOKEN“ und authentifiziert private Artefakt-Uploads.
Vorkompilierte Binärdateien unter Linux/macOS? Standardmäßig nein (lokale Kompilierung = ABI-Robustheit), aber ja unter Windows (DLL).
Ersetzt Pi offiziell PECL/Pickle? Der Adoptionsprozess durchläuft auf PHP-Seite RFC/Abstimmungen; die Tendenz geht dahin, Pi als bevorzugten Pfad zu empfehlen. So oder so, Sie können es sofort nutzen.
Best Practices, die Sie heute anwenden können
- Deklarieren Sie Ihre Erweiterungen in
composer.json
("ext-redis": "*"
) und dokumentieren Sie die unterstützten PHP-Versionen. * Standardisieren Sie Ihre CI-Pipelines rund umpi install
(anstelle von betriebssystemspezifischen Skripten). * Veröffentlichen Sie vollständige Metadaten der Erweiterungsseite: PHP/Betriebssystem-Einschränkungen, Signaturen, Build-Anweisungen. * Zwischenspeichern Sie den Pi-Cache in CI und korrigieren Sie Erweiterungsversionen in der Produktion (über stabile Tags).
Abschluss
Pi bringt endlich die Ergonomie und Zuverlässigkeit, die Composer Bibliotheken bot, in PHP-Erweiterungen: einen einheitlichen, reproduzierbaren, skriptfähigen, plattformübergreifenden Workflow – und zugeschnitten auf moderne Realitäten (Monorepos, privat, CI, Windows).
Wenn Sie schon einmal eine Erweiterung abgelehnt haben, weil die Installation riskant oder zeitaufwändig erschien, versuchen Sie es noch einmal mit Pi. Vielleicht kommen Sie ja sogar auf den Geschmack. 🚀
Anhänge – Befehlserinnerung
# Inventar der von Pi verwalteten Erweiterungen pi show
# Fügen Sie ein privates Erweiterungs-Repository hinzu: pi repo add my-ext vcs https://github.com/acme/php-ext-foo.git
# Laden Sie die Quellen herunter pi download xdebug
# Build entsprechend der aktuellen OS/PHP-Version pi build xdebug
# Installieren und aktivieren Sie pi install xdebug pi install pcov --with-php-path=/usr/bin/php8.3
# Deinstallieren Sie pi und deinstallieren Sie xdebug
🌍 Gesellschaft
- Wo sind die Frauen in der Technologiegeschichte geblieben? 2.0 – Laura Durieux Inspirierende Konferenz, die den Platz der Frauen in der Geschichte und die Bedeutung der Inklusion in der Technologie hervorhebt.
🎉 Abschluss
Den Abschluss der Konferenz bildete eine gemeinsame Rede, in der die Bedeutung der Gemeinschaft hervorgehoben und ein Datum für die Ausgabe 2026 festgelegt wurde.
📌 Fazit
Diese Ausgabe 2025 war geprägt von:
- Die Allgegenwärtigkeit von FrankenPHP, das in den meisten REX-Versionen vorhanden ist. * Die rasante Entwicklung der API-Plattform 4.2 mit Fokus auf Automatisierung, Leistung und Echtzeit. * Der Schwerpunkt liegt auf Best Practices: Composer, API-Filter, Fehlerbehandlung, Typen. * Eine Community, die weiterhin Innovationen hervorbringt und sich gleichzeitig mit menschlichen und gesellschaftlichen Problemen befasst.
Ein Pflichttermin für jeden Entwickler, der bei PHP- und Symfony-Technologien an der Spitze bleiben möchte.