creative-web-solution/imagine-bundle
Installation:
composer require liip/imagine-bundle
Add to config/bundles.php (Symfony Flex handles this automatically).
Configure Filter Sets:
Define a filter set in config/packages/liip_imagine.yaml:
liip_imagine:
filter_sets:
my_thumbnail:
filters:
thumbnail: { size: [100, 100], mode: outbound }
First Use Case: Generate a thumbnail in a controller:
use Liip\ImagineBundle\Imagine\Cache\CacheManager;
use Liip\ImagineBundle\Imagine\Filter\FilterManager;
public function show(Image $image, CacheManager $cacheManager, FilterManager $filterManager)
{
$filter = $filterManager->getFilter('my_thumbnail');
$path = $cacheManager->getBrowserPath($image->getPath(), $filter);
return new Response(file_get_contents($path));
}
config/packages/liip_imagine.yaml (default config)src/Controller/ImageController.php (example usage)src/Entity/Image.php (if using Doctrine)Use the FilterManager to apply filters dynamically based on user input or business logic:
$filter = $filterManager->getFilter('thumbnail_large');
if ($user->isPremium()) {
$filter = $filterManager->getFilter('thumbnail_premium');
}
Generate multiple filter sets for different breakpoints and serve the appropriate one:
liip_imagine:
filter_sets:
responsive_small: { filters: { thumbnail: { size: [300, 300] } } }
responsive_large: { filters: { thumbnail: { size: [1200, 1200] } } }
Use in Twig:
{% for filter in ['responsive_small', 'responsive_large'] %}
<source srcset="{{ asset(app.liip_imagine.filter(filter).getBrowserPath(image.path)) }}"
media="(min-width: {{ loop.index0 * 300 + 300 }}px)">
{% endfor %}
Annotate entities to auto-generate paths:
use Liip\ImagineBundle\Annotation\Filter;
/**
* @ORM\Entity
* @Filter("my_thumbnail")
*/
class ProductImage {
// ...
}
Access the filtered path:
$productImage->getFilteredPath('my_thumbnail');
Process images in bulk via console:
php bin/console liip:imagine:cache:remove --filter=my_thumbnail
php bin/console liip:imagine:cache:generate --filter=my_thumbnail
LiipImagineBundle\Form\Type\ImagineType for file uploads with auto-filtering.return $this->json([
'original' => $image->getPath(),
'thumbnail' => $cacheManager->getBrowserPath($image->getPath(), $filter),
]);
X-Sendfile or X-Accel-Redirect.Cache Invalidation:
php bin/console cache:clear
php bin/console liip:imagine:cache:remove --filter=*
cache:generate to rebuild all filtered images.File Permissions:
Ensure the cache directory (e.g., var/cache/liip_imagine) is writable by the web server user.
Memory Limits:
Large images may hit PHP’s memory_limit. Adjust in php.ini or use gd/imagick optimizations:
liip_imagine:
driver: gd
# or
driver: imagick
Filter Chaining:
Filters execute in order. Place thumbnail before watermark to avoid scaling artifacts.
Doctrine Proxy Issues:
If using annotations, ensure LiipImagineBundle is loaded before Doctrine ORM in config/bundles.php.
$path = $cacheManager->getBrowserPath($originalPath, $filter);
file_exists($path); // Verify file exists
liip_imagine:
debug: true
dump($filterManager->getFilterNames());
Custom Filters:
Create a custom filter by implementing Liip\ImagineBundle\Imagine\Filter\FilterInterface:
use Liip\ImagineBundle\Imagine\Filter\FilterConfigurationInterface;
class CustomFilter implements FilterInterface {
public function apply(FilterConfigurationInterface $configuration) {
// Modify $configuration->getImagineObject()
}
}
Register in config/packages/liip_imagine.yaml:
liip_imagine:
filters:
custom:
custom_filter: ~
Dynamic Filter Sets: Generate filter sets programmatically:
$filterManager->createFilter('dynamic_'.uniqid(), [
'thumbnail' => ['size' => [$width, $height]],
]);
Event Listeners:
Listen to liip_imagine.filter.post_generate to post-process images:
use Liip\ImagineBundle\Imagine\Event\FilterEvent;
$eventDispatcher->addListener(
'liip_imagine.filter.post_generate',
function (FilterEvent $event) {
// $event->getImagineObject() is the processed image
}
);
Storage Backends:
Extend Liip\ImagineBundle\Imagine\Cache\CacheManager to support custom storage (e.g., S3):
class S3CacheManager extends CacheManager {
protected function getCachePath($path) {
return 's3://bucket/' . $path;
}
}
How can I help you explore Laravel packages today?