Deterministic, query‑driven image generation for Laravel — inspired by vite-imagetools.
- Call it once in Blade/PHP and get a public URL:
{{ ImageTools::asset('public/images/hero.jpg?w=1200&h=630&fit=contain&format=webp&q=82') }}
- Files are written to your configured filesystem disk with stable names
(e.g.
hero--a1b2c3d4e5.webp), perfect for long‑lived CDN caching. - A tiny PHP manifest maps your canonical request to the stored file, so subsequent calls are instant.
- 🔁 Deterministic filenames based on the source + sorted query options
- 🧩 Simple query API:
w,h,fit,q,format - 📦 One disk to rule them all — works with
public, S3/R2 or any Laravel disk - 🔎 Scanner command to pre‑generate all images referenced in your code
- 🧹 Clear command to remove generated files & the manifest
- PHP 8.2+
- Laravel 10+ (works with 10/11/12)
- Image driver: Imagick (recommended) or GD for
spatie/image
composer require isapp/laravel-imagetoolsAuto‑discovery will register the service provider and the ImageTools facade.
If you want to customize defaults, publish the config file:
php artisan vendor:publish --provider="Isapp\\ImageTools\\ServiceProvider"<img
src="{{ ImageTools::asset('public/images/placeholder.jpg?w=640&q=75&format=webp') }}"
width="640"
height="360"
alt="Placeholder"
/>Pure PHP
use Isapp\\ImageTools\\Facades\\ImageTools;
$url = ImageTools::asset('resource/images/placeholder.jpg?w=640&q=75&format=webp');Also supported (and detected by the scanner):
{{ app(Isapp\ImageTools\ImageTools::class)->asset('resource/images/pic.jpg?w=800') }}
{{ app('image-tools')->asset('resource/images/pic.jpg?w=800') }}
{{ \Illuminate\Support\Facades\App::make('image-tools')->asset('resource/images/pic.jpg?w=800') }}
{{ App::make(Isapp\ImageTools\ImageTools::class)->asset('resource/images/pic.jpg?w=800') }}All options live in config/image-tools.php (with inline comments). You can also control them via ENV:
IMAGE_TOOLS_DISK=public
IMAGE_TOOLS_MANIFEST_PATH=bootstrap/cache/image-tools.php
IMAGE_TOOLS_BLADE_PATHS=resources/views,modules/*/resources/views
IMAGE_TOOLS_PHP_PATHS=app,modulesKey options:
disk— Laravel filesystem disk where processed files are written and served from (public,s3,r2, …).manifest_path— Path to the PHP manifest file that stores the mapping.blade_paths— Directories with Blade templates to scan for usages.php_paths— Additional PHP directories to scan (controllers, services, etc.).
The request is canonicalized: query keys are sorted before hashing, so
?h=630&w=1200equals?w=1200&h=630.
| Key | Type | Description |
|---|---|---|
w |
int |
Target width (px). |
h |
int |
Target height (px). |
fit |
enum |
Geometry mode from Spatie\Image\Enums\Fit (e.g. Contain, Fill, Max, …). Requires w and h. |
q |
int |
Output quality (1..100). |
format |
enum |
Output format: jpeg, png, gif, webp, avif. |
Scans your codebase and generates images for discovered usages.
php artisan imagetools:generateThe scanner looks into config('image-tools.blade_paths') and config('image-tools.php_paths') and detects:
ImageTools::asset('…')- Container‑resolved calls (e.g.
app(ImageTools::class)->asset('…'),app('image-tools')->asset('…'),App::make(...)->asset('…'))
Deletes all files referenced in the current manifest and then removes the manifest file.
php artisan imagetools:clear- A processed file on the configured disk, under
image-tools/<name>--<hash>.<ext>. - A PHP manifest (by default
bootstrap/cache/image-tools.php) with entries like:return [ 'resource/images/hero.jpg?h=630&w=1200&fit=contain&format=webp&q=82' => [ 'path' => 'image-tools/hero--a1b2c3d4e5.webp', 'disk' => 'public', ], ];
- Deterministic names → long CDN cache is safe; change options or the source to bust the cache.
- Disks: for S3/R2 configure a public bucket or use signed URLs as needed.
- Quality/Formats:
webp/avifusually win; measure before/after.
Class ...\ImageTools not found— ensure the package is installed and auto‑discovered; runcomposer dump-autoload.ImagickException/ missing extension — install and enable Imagick (preferred) or GD for your PHP runtime.width(): Argument #1 must be of type int— pass numeric values in the query (w=640, notw=640px).fitrequireswandh— when usingfit, provide both dimensions.- No URL / 404 — check the configured
diskhas a URL generator (php artisan storage:linkforpublicdisk).
This package follows SemVer. Until 1.0.0, minor versions (0.x) may include breaking changes.
If you discover a security issue, please email [email protected] instead of opening a public issue.
Contributions are welcome! If you have suggestions for improvements, new features, or find any issues, feel free to submit a pull request or open an issue in this repository.
Thank you for helping make this package better for the community!
This project is open-sourced software licensed under the MIT License.
You are free to use, modify, and distribute it in your projects, as long as you comply with the terms of the license.
Built by ISAPP. Uses the excellent spatie/image.
Check out our software development services at isapp.be.
