L'API image first-party de Laravel couvrait l'écriture depuis la 13.20 — upload, transformation, stockage sur un disque — mais servir une image redimensionnée en HTTP exigeait du code répétitif : appeler toBytes(), construire une réponse et définir le content-type à la main. Laravel 13.25 corrige cela avec trois ajouts.
Premièrement, Image implémente désormais le contrat Responsable : une instance d'image est une valeur de retour valide pour une route ou un contrôleur. Le framework appelle toResponse(), exécute le pipeline de façon paresseuse, renvoie les octets avec un statut 200 et définit le Content-Type d'après la sortie produite — un JPEG stocké mais servi en WebP donne bien image/webp. L'instance étant paresseuse, la transformation ne s'exécute que lorsque les octets sont réellement demandés.
La réponse par défaut ne contient aucun en-tête de cache. Appeler toResponse($request) soi-même renvoie une Illuminate\Http\Response, ce qui donne accès à setMaxAge(), setPublic(), setEtag() et au reste de l'API. Pour du vrai trafic, l'article recommande de générer le fichier dérivé une seule fois puis de le servir depuis le disque, en incluant le timestamp updated_at du modèle dans le nom de fichier afin que les photos mises à jour obtiennent de nouveaux chemins sans invalidation de cache.
Deuxièmement, toFormat() est maintenant public et accepte directement webp, jpg, jpeg, png, gif, avif, heic, heif (normalisé en heic) et bmp — fini les blocs match pour les formats venant de la requête. Une valeur invalide lève une ImageException (une 500, pas une 404), d'où l'intérêt des contraintes de route ou de la validation. Cela rend très courts les endpoints AVIF avec repli, combinés à l'élément <picture>.
Troisièmement, Image::fromStream() crée une instance depuis une ressource stream, par exemple Storage::disk('s3')->readStream($path). La lecture est paresseuse ; un stream vide lève « Invalid stream image data. » à l'exécution du pipeline. La méthode complète fromPath(), fromStorage(), fromUpload(), fromUrl(), fromBytes() et fromBase64() pour les handles comme php://input ou les fichiers lus depuis des archives.
L'article se termine par un endpoint complet : largeur validée (bornée entre 32 et 2000) et format, lecture en stream depuis S3, mise à l'échelle, conversion, qualité 80 et cache public d'un an — le tout protégé par une route signée pour empêcher la génération de variantes arbitraires aux frais de votre facture de stockage. Les trois changements ont été contribués par Caleb White via les PR #61111, #61109 et #61110 du framework.
Commentaires
Pas encore de commentaire — écris le premier.
Lance la discussion
Pas de compte ni de mot de passe — saisis simplement ton adresse e-mail et nous t’envoyons un lien de connexion à usage unique. Première visite ? Tout se met en place automatiquement.
Ton évaluation sera appliquée automatiquement après ta connexion.
Vérifie ta boîte mail
Nous avons envoyé un lien de connexion à …. Ouvre-le sur cet appareil — cet onglet te connectera automatiquement.
Rien reçu ? Vérifiez le dossier spam — et marquez le message « Non spam » pour qu'il arrive directement la prochaine fois.