Die Logzeile lautete `Redirect allowed: host=trusted.example`, und der Redirect ging irgendwohin, nur ganz sicher nicht zu trusted.example. Ich habe eine lange Nacht mit parse_url() verbracht und mit einer URL, die ein Browser anders las als unsere Allowlist. Wenn mich also jemand fragt, was das große Ding an PHP 8.5 ist, sage ich nicht „der Pipe-Operator“, auch wenn das auf jeder Konferenzfolie steht. Meine Antwort ist die URI-Extension, und die verteidige ich hier.
<?php
use Uri\Rfc3986\Uri;
$uri = new Uri('https://php.net/releases/8.5/en.php');
echo $uri->getHost(); // "php.net"Erst mal zur Lage. PHP 8.5 ist am 20. November 2025 erschienen. Laravel 12 und 13 laufen beide auf PHP 8.3 bis 8.5, Hoster bieten es an, und das nächste Release kommt diesen November. Ein guter Zeitpunkt also, nicht mehr zu fragen, was neu ist, sondern was sich in unseren Codebases tatsächlich verändert hat. Der Pipe-Operator bekommt fast die ganze Aufmerksamkeit. Was in deinen Incident-Reports zählen wird, ist `Uri\Rfc3986\Uri` samt seinem WHATWG-Geschwister.
Hier das beste Argument für die Gegenseite, und es ist ein starkes. Pipes verändern, wie sich Code auf jedem Bildschirm liest, den du öffnest. Verschachtelte Aufrufe, die man von innen nach außen lesen muss, sind eine kleine Steuer, die du den ganzen Tag zahlst, und `|>` schafft sie für jede normale Funktion ab, ganz ohne Collection oder `Str::of()`-Wrapper. Ein Feature, das du in hundert Dateien siehst, kann leicht wichtiger sein als eins, das du in dreien benutzt. Das gestehe ich zu. Und ich lege noch nach: `array_first()` und `array_last()` werden mehr hässliche `array_key_last()`-Konstrukte verschwinden lassen, als wir alle zugeben wollen.
Mein Problem ist, dass sich Lesbarkeitsgewinne dünn verteilen, und der Pipe-Operator hat ein paar Ecken und Kanten, die sie bescheiden halten. Jeder Schritt muss ein Callable mit genau einem Argument sein. Sobald du `str_replace` brauchst, schreibst du also eine Arrow Function und musst sie obendrein noch in Klammern packen. Echte Pipelines werden am Ende eine Mischung aus `trim(...)` und `(fn($s) => ...)`. Das ist schöner als Verschachtelung, aber nicht dramatisch schöner. Ein Team, das ihn nie einsetzt, verliert nichts, was eine gut benannte lokale Variable nicht zurückgeben könnte.
Beim URL-Parsing sieht das anders aus. parse_url() war schon immer nachsichtig: Es lieferte dir ein Array für Eingaben, die ein Browser, ein Proxy und dein HTTP-Client jeweils unterschiedlich lesen würden. Genau in dieser Lücke entstehen Open Redirects und Umgehungen von SSRF-Allowlists. Jetzt bekommst du ein Objekt, das nach einem veröffentlichten Standard gebaut ist, entweder RFC 3986 oder WHATWG, und du wählst den, der zum System auf der anderen Seite passt. Diese Wahl ist das eigentliche Upgrade. Du musst entscheiden, ob du wie ein Server oder wie ein Browser validierst, eine Frage, die dir parse_url() nie gestellt hat.
Der Aufruf selbst ist fast zu simpel, um ihn zu zeigen, und genau darum geht es mir eigentlich. Du brauchst kein Refactoring, keine Styleguide-Debatte und keine Teamabstimmung. Du suchst die Stellen, an denen ein Host oder ein Schema darüber entscheidet, wer reinkommt, und tauschst das Parsing aus.
Um dem Rest von 8.5 gerecht zu werden: `#[\NoDiscard]` argumentiert in dieselbe Richtung und fängt ein `save()` ab, dessen false-Rückgabe niemand geprüft hat, und Fatal Errors mit Backtraces werden so manche Jagd nach Memory-Exhaustion verkürzen. Da würde ich als Nächstes hinschauen. Pipes kommen danach, in neuen Helpern und Data Mappern, wann immer sie eine Zeile klarer machen. Viele von uns schreiben auch in Go fröhlich verschachtelte Aufrufe, und daran ist noch keine Karriere zerbrochen.
Deshalb meine Frage an dich, denn du kennst deine Codebase und ich nicht. Falls du schon auf 8.5 umgestiegen bist: Was hast du zuerst geändert, und hat irgendetwas davon einen echten Bug gefunden, oder ging es nur darum, dass der Code besser aussieht? Falls du parse_url() durch die URI-Extension ersetzt hast: War RFC 3986 oder WHATWG der richtige Standard für deine Redirects und Webhooks, und wie hast du das entschieden?




Kommentare
Noch keine Kommentare — schreib den ersten.
Starte die Diskussion
Kein Konto, kein Passwort nötig — gib einfach deine E-Mail-Adresse ein, wir senden dir einen einmaligen Anmelde-Link. Beim ersten Mal bist du damit automatisch angemeldet.
Deine Bewertung wird nach der Anmeldung automatisch übernommen.
Schau in dein Postfach
Wir haben einen Anmelde-Link an … gesendet. Öffne ihn auf diesem Gerät — dieser Tab meldet dich automatisch an.
Nichts angekommen? Wirf einen Blick in den Spam-Ordner — und markiere die Mail dort als „Kein Spam“, dann landet sie künftig direkt im Postfach.