Laravels First-Party-Bild-API deckte seit Version 13.20 den Schreibpfad ab – Upload, Transformation, Ablage auf einem Disk –, doch das Ausliefern eines skalierten Bildes über HTTP erforderte Boilerplate: toBytes() aufrufen, eine Response bauen und den Content-Type manuell setzen. Laravel 13.25 schließt diese Lücke mit drei Neuerungen.

Erstens implementiert Image nun den Responsable-Contract: Eine Bild-Instanz ist ein gültiger Rückgabewert aus Route oder Controller. Das Framework ruft toResponse() auf, führt die Pipeline lazy aus, liefert die Bytes mit Status 200 und setzt den Content-Type aus dem erzeugten Output – ein als JPEG gespeichertes, als WebP ausgeliefertes Bild ergibt korrekt image/webp. Da die Instanz lazy ist, läuft die Transformation nur, wenn tatsächlich Bytes angefragt werden.

Die Standard-Response enthält keine Cache-Header. Wer toResponse($request) selbst aufruft, erhält eine Illuminate\Http\Response und kann setMaxAge(), setPublic(), setEtag() und die übrige Response-API nutzen. Für echten Traffic empfiehlt der Artikel, die abgeleitete Datei einmal zu erzeugen und danach vom Disk auszuliefern – mit dem updated_at-Zeitstempel des Models im Dateinamen, damit aktualisierte Fotos neue Pfade ohne Cache-Invalidierung erhalten.

Zweitens ist toFormat() jetzt öffentlich und akzeptiert direkt webp, jpg, jpeg, png, gif, avif, heic, heif (wird zu heic normalisiert) und bmp – match-Anweisungen für request-gesteuerte Formate entfallen. Ungültige Werte werfen eine ImageException (ein 500, kein 404), daher werden Route-Constraints oder Validierung empfohlen. AVIF-mit-Fallback-Endpunkte in Kombination mit dem <picture>-Element werden damit sehr kurz.

Drittens erzeugt Image::fromStream() eine Instanz aus einer Stream-Ressource, etwa Storage::disk('s3')->readStream($path). Das Lesen ist lazy; ein leerer Stream wirft erst bei der Ausführung der Pipeline „Invalid stream image data.". Die Methode ergänzt fromPath(), fromStorage(), fromUpload(), fromUrl(), fromBytes() und fromBase64() für Handles wie php://input oder Dateien aus Archiven.

Zum Abschluss zeigt der Artikel einen kompletten Endpoint: validierte Breite (begrenzt auf 32–2000) und Format, Streaming von S3, Skalierung, Konvertierung, Qualität 80 und ein Jahr öffentlicher Cache – abgesichert über eine signierte Route, damit niemand beliebige Varianten auf Kosten der Storage-Rechnung erzeugt. Alle drei Änderungen stammen von Caleb White aus den Framework-PRs #61111, #61109 und #61110.