onigoetz/imagecache
Onigoetz ImageCache is a Laravel package for on-the-fly image manipulation and caching. Define reusable templates, apply URL-based filters and resizing, and serve cached images through a simple route while keeping originals untouched.
Check your Laravel version first. 3.2.0 is the release that moved the package to Laravel 11/12 and dropped the older, EOL branches. If you're still on Laravel 9/10, pin ^3.1 and plan the framework upgrade before taking this in — there's no compatibility shim here, it's a hard constraint change in composer.json.
composer require onigoetz/imagecache
Publish the config and read it end to end — this is the package. Everything (routes, templates, cache location, driver, quality) is defined there:
php artisan vendor:publish --tag=config
Make sure the cache directory is writable and reachable by the web server. If you're serving generated files from storage/, you'll need php artisan storage:link and the usual permission checks.
Define at least one template in config/imagecache.php — a name plus a list of manipulation actions (resize, crop, fit, etc.).
First real use case: drop a generated URL into a Blade view:
<img src="{{ Image::url('uploads/hero.jpg', 'medium') }}" alt="">
Hit the page, confirm the file lands in the cache directory, then confirm the second request is served straight from disk without re-processing.
Where to look first when something's wrong: the published config (template names and source path roots), then the cache directory contents, then the route the package registered.
Treat templates as design tokens, not one-offs. Define a small set (thumb, card, hero, plus a 2x variant) and reference them by name everywhere. Scattering inline dimensions means every layout change becomes a code change in a dozen views.
Responsive images via srcset. Generate one template per breakpoint and compose them in a Blade partial or component so the <picture>/srcset markup lives in exactly one place:
<img src="{{ Image::url($path, 'card') }}"
srcset="{{ Image::url($path, 'card') }} 1x, {{ Image::url($path, 'card_2x') }} 2x"
alt="{{ $alt }}">
Wrap the facade, don't call it directly from views. A tiny helper or Blade component that takes a model/path and returns the URL gives you one place to swap in a CDN host, add a version query string, or return a placeholder for missing files.
Pair templates with your upload pipeline. Resize-on-render is fine for a handful of sizes, but if you have a hard requirement that images exist before a page goes live, generate the common templates as a post-upload job and let the route serve them as a fallback. This is also how you avoid the first-visitor latency hit on cold cache.
Protect private images at the route level. For anything user-specific, apply middleware to the package route (or wrap it) so authorization is checked before the file is served. Don't rely on unguessable filenames.
Custom actions belong in a service provider. If your design needs something the built-in actions don't cover (specific watermark placement, brand-specific padding), register your own action rather than post-processing the cached file elsewhere — otherwise the cache and the post-processor drift apart.
Test with Storage::fake-style isolation where you can, and assert on the URL shape rather than binary image output. For visual regressions, spot-check the generated files in a staging environment instead of trying to assert pixel output in CI.
hero.jpg in place leaves the old derivative sitting in the cache. Either version your filenames, clear the cache directory as part of deploy, or key the URL on a file hash. This is the single most common "why is my image wrong" bug with this class of package.php artisan route:list early.storage/logs before touching config.How can I help you explore Laravel packages today?