Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Image Symfony Laravel Package

intervention/image-symfony

Symfony integration for Intervention Image, providing a ready-to-use image manager service for resizing, cropping, and applying filters. Configure drivers and options once, then inject the manager anywhere to handle uploads and thumbnails with clean, expressive code.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and wire it up

4.0.0 is a major release that exists solely to track Intervention Image v4. Install both majors together so Composer can't resolve a mismatched pair:

composer require intervention/image-symfony:^4.0 intervention/image:^4.0

Symfony Flex should register the bundle automatically; if not, add it to config/bundles.php:

Intervention\Image\Symfony\ImageSymfonyBundle::class => ['all' => true],

Create config/packages/intervention_image.yaml with the minimum:

intervention_image:
    driver: gd   # or imagick

Both drivers require the corresponding PHP extension (ext-gd / ext-imagick). Pick gd for portability and CI, imagick when you need better format support or quality control. Check the composer.json of both packages for the new PHP floor — image majors typically raise it, and a failed resolution on PHP version is the most common install error here.

Where to look first

  1. The bundle's DependencyInjection/Configuration.php and *Extension.php — still the authoritative list of config keys. The 4.0.0 release note only mentions the underlying library bump, so you should not assume any config schema change; confirm by diffing Configuration.php against what you have.
  2. The Intervention\Image v4 docs. The Symfony package is a thin DI wrapper; 90% of what you'll do day-to-day is the underlying library's API, and v4 is a fresh major — re-read the upgrade guide even if you knew v3 well.
  3. bin/console debug:container ImageManager to confirm the service ID and autowiring alias survived the bump.

First use case

Inject the manager and process an upload in a controller:

use Intervention\Image\ImageManager;

public function upload(Request $request, ImageManager $manager): Response
{
    $file = $request->files->get('photo');
    $image = $manager->read($file->getPathname())
        ->cover(1200, 630)
        ->toWebp(82);

    $image->save($this->getParameter('kernel.project_dir').'/public/uploads/hero.webp');

    return $this->redirectToRoute('home');
}

Verify each method name against the v4 docs before copying this in — read(), cover(), and the encoder methods are the surface most likely to have been renamed or re-signatured in a new major. If it autowires and encodes, you're done; that's the whole integration surface for most projects.

Implementation Patterns

Constructor injection everywhere

The manager is stateless and safe to inject into controllers, services, message handlers, and console commands. Favor injecting it over calling static helpers so tests can swap it. If v4 changed the manager's constructor signature, the bundle's service definition is where that's absorbed — your injection points should not need to change.

HTTP responses

For on-the-fly resizing (thumbnails, avatars), read from disk or a stream and return the encoded image:

$image = $manager->read($path)->scale(width: 200);
return new Response($image->toJpeg(), 200, ['Content-Type' => 'image/jpeg']);

Add Cache-Control / ETag headers yourself — the bundle does not give you an HTTP caching layer out of the box.

Background processing

Image work is CPU- and memory-bound. Move it to a Symfony Messenger handler:

#[AsMessageHandler]
class GenerateThumbnailHandler
{
    public function __construct(private ImageManager $manager, private FilesystemOperator $storage) {}

    public function __invoke(GenerateThumbnail $msg): void
    {
        $image = $this->manager->read($this->storage->read($msg->path))->cover(400, 400);
        $this->storage->write($msg->thumbPath, $image->toWebp()->toString());
    }
}

This pairs naturally with Flysystem — read the source stream, write the derivative stream, never touch local temp files explicitly. A major-version rollover is a good moment to do the upgrade behind the queue: deploy workers first, let them drain, then ship the web tier.

Per-environment driver configuration

Use when@test to force GD in tests and when@prod to use Imagick with tuned options:

when@test:
    intervention_image:
        driver: gd
when@prod:
    intervention_image:
        driver: imagick
        options:
            autoOrientation: true

Deriving variants in a service

Wrap the manager in your own Thumbnailer service so resize rules, quality, and naming live in one place rather than being scattered across controllers. This is also where you'd add cache-key logic (see below) — and where a v4 encoder change only has to be absorbed once.

Custom defaults via decoration

If you need project-wide defaults (e.g., always strip metadata, always encode WebP at quality 80), decorate the manager:

App\Image\ConfiguredImageManager:
    decorates: Intervention\Image\ImageManager

Or simply expose your own facade service and forbid direct injection via code review — for a package this thin, a thin wrapper is often cleaner than fighting DI. A decorator also gives you a single seam to shim any v4 API renames.

Testing

Use real fixture images and assert on dimensions/format, not byte equality (drivers differ across versions). Treat this upgrade as a fixture reset: v4 encoders may emit different bytes for the same input, so any golden-file or snapshot assertion on encoded output will fail for reasons unrelated to your code. Regenerate fixtures once, commit them, and keep asserting on dimensions, format, and rough file-size bands.

Gotchas and Tips

This is a compatibility major, not a feature major. The 4.0.0 note contains exactly one line: support for Intervention Image v4.0.0. Expect no new config keys, no new services, no new extension points. Budget the upgrade as "chase the underlying library's breaking changes," not "learn a new bundle."

You cannot mix majors. The bundle's composer.json will require intervention/image:^4.0. If a transitive dependency pins v3, resolution fails. Diagnose with:

composer why-not intervention/image 4.0
composer why-not intervention/image-symfony 4.0

Run this before editing composer.json so you know whether a third-party image plugin is the blocker.

v4 API vs. every tutorial you'll find. Most blog posts and Stack Overflow answers still show v2 (Image::make($path), ->resize(300, null)) and a growing pile show v3 ($manager->read(), named args). v4 has reset that surface again. If something "doesn't exist," check which major the answer was written for before assuming the install is broken — and prefer the upgrade guide over snippets.

The integration is thin — expect to read source. With a tiny star count and no visible dependents, issues and examples are sparse. When config keys or service IDs are unclear, read the bundle's Configuration class and services.yaml rather than trusting the README. Keep intervention/image and intervention/image-symfony pinned to compatible minors; a floating ^4.0 on both is fine, a floating constraint on one and a pinned one on the other is not.

Invalidate your derivative cache on deploy. If you cache generated images keyed on source-hash-plus-transform-params, a v4 encoder change produces visually similar but byte-different output under identical keys. Bump a version prefix in the cache key as part of the 4.0.0 rollout rather than waiting for users to report stale images.

Imagick policy.xml will bite you in containers. Docker base images often ship an imagick policy that blocks PDFs, large dimensions, or certain coders. If operations silently fail or throw — especially after a major bump where the failing call may have moved — check /etc/ImageMagick-*/policy.xml before blaming the bundle.

Memory and timeouts. A 4000×3000 JPEG decoded into GD or Imagick can consume hundreds of MB. Set memory_limit explicitly for queue workers and consider ->scale() before ->cover() for very large inputs. Never do heavy processing synchronously on a user request path.

EXIF orientation. Photos from phones will appear rotated unless autoOrientation is enabled in the options config. It's off by default in the underlying library; turn it on globally. Re-verify the option name in v4 — it is exactly the kind of setting that gets renamed in a major.

Animated formats. GIF/WebP animation decoding is opt-in (decodeAnimation). If frames vanish after processing, that's the option you forgot. Same caveat: confirm the v4 spelling.

Filesystem permissions for cache/temp. If your config points at a writable directory (cache, temp), ensure it exists and is writable by the PHP user — especially in read-only container filesystems where only /var/cache and /tmp are mounted writable.

Cache invalidation. If you add your own derivative cache, key on the source file's hash plus the transform parameters, not on mtime alone — deploys and rsync can reset mtimes.

Multiple managers / explicit aliases. If you register additional ImageManager instances (e.g., different drivers per feature), autowiring by type becomes ambiguous. Define named aliases and inject by argument name or explicit service ID. After a major bump, re-run debug:container to confirm the aliases still exist before you assume your autowiring is fine.

Extension points are Symfony-native, not package-native. The package offers no events or plugin hooks, and 4.0.0 adds none. Use service decoration, compiler passes, and your own wrapper services — all standard Symfony DI — rather than looking for integration-specific extension APIs.

Upgrade path. 3.x → 4.0 is driven entirely by intervention/image 3.x → 4.0. Read the underlying library's changelog and upgrade guide first; the Symfony package will rarely be the source of a breaking change, and its release notes will rarely tell you what actually broke. Pin the major on both, upgrade in a branch, run your image test suite, and expect the failures to be in method names and encoder output — not in the bundle wiring.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin