php 55 lines · 7 steps

Generating responsive images in a Laravel listener

A queued event listener resizes an uploaded image into multiple WebP widths and records each variant in the database.

Explained by highlit
1<?php
2 
3namespace App\Listeners;
4 
5use App\Events\MediaUploaded;
6use App\Models\ImageVariant;
7use Illuminate\Contracts\Queue\ShouldQueue;
8use Illuminate\Support\Facades\Storage;
9use Intervention\Image\Laravel\Facades\Image;
10 
11class GenerateResponsiveVariants implements ShouldQueue
12{
13 public string $queue = 'media';
14 
15 protected array $widths = [320, 640, 1024, 1920];
16 
17 public function handle(MediaUploaded $event): void
18 {
19 $media = $event->media;
20 $disk = Storage::disk('public');
21 
22 $source = Image::read($disk->get($media->path));
23 $originalWidth = $source->width();
24 
25 foreach ($this->widths as $width) {
26 if ($width > $originalWidth) {
27 continue;
28 }
29 
30 $variant = (clone $source)->scaleDown(width: $width);
31 $variantPath = $this->variantPath($media->path, $width);
32 
33 $disk->put($variantPath, (string) $variant->toWebp(quality: 82));
34 
35 ImageVariant::updateOrCreate(
36 ['media_id' => $media->id, 'width' => $width],
37 [
38 'path' => $variantPath,
39 'height' => $variant->height(),
40 'mime_type' => 'image/webp',
41 'bytes' => $disk->size($variantPath),
42 ],
43 );
44 }
45 
46 $media->update(['variants_generated_at' => now()]);
47 }
48 
49 protected function variantPath(string $path, int $width): string
50 {
51 $info = pathinfo($path);
52 
53 return "{$info['dirname']}/{$info['filename']}-{$width}w.webp";
54 }
55}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Implementing ShouldQueue moves slow work like image encoding off the request cycle onto a background worker.
  2. 2Skipping widths larger than the source avoids upscaling and keeps variants faithful to the original.
  3. 3updateOrCreate makes the listener safe to retry without producing duplicate variant rows.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Generating responsive images in a Laravel listener — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code