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

Avalanche123 Imagine Bundle Laravel Package

slauta/avalanche123-imagine-bundle

A Symfony bundle that integrates the Imagine image manipulation library, letting you define filters and generate cached thumbnails, crops, and resized images through configurable routes and Twig helpers. Useful for responsive image workflows and on-the-fly asset processing.

View on GitHub
Deep Wiki
Context7

Getting Started

This bundle is a thin Symfony wrapper around the Imagine PHP image library. Its whole job is to let you declare named image filters in YAML and apply them to images from Twig (and PHP), generating and caching the transformed images on first request. It is a fork of the long-deprecated avalanche123/imagine-bundle, so treat it as a legacy integration for Symfony 2.x / early 3.x — the useful steps are the same as the original.

Minimal setup:

  1. Install with the fork's package name (the original was avalanche123/imagine-bundle):

    composer require slauta/avalanche123-imagine-bundle
    

    This pulls in imagine/imagine (check which version lands; ~0.6/0.7 era API). Make sure the GD or Imagick extension is present on the host.

  2. Register the bundle in app/AppKernel.php (namespace is inherited from the original — confirm the exact class name in the package's vendor/ tree before pasting):

    new Avalanche\Bundle\ImagineBundle\AvalancheImagineBundle(),
    
  3. Import the bundle routing so the controller that serves generated images is reachable:

    # app/config/routing.yml
    _imagine:
        resource: "@AvalancheImagineBundle/Resources/config/routing.xml"
        prefix:   /
    
  4. Configure at least one filter under the bundle's config key (avalanche_imagine in the original; verify if the fork renamed it):

    # app/config/config.yml
    avalanche_imagine:
        driver: gd
        web_root: %kernel.root_dir%/../web
        cache_prefix: media/cache
        filters:
            thumb:
                type: thumbnail
                options: { size: [120, 90], mode: outbound }
    
  5. First use case — a thumbnail in a template. The canonical usage is the bundle's Twig filter (original name apply_filter; forks have used imagine_filter):

    <img src="{{ 'images/photo.jpg' | apply_filter('thumb') }}" alt="Photo">
    

    The output is a URL like /media/cache/thumb/images/photo.jpg. On first hit, the controller reads images/photo.jpg, applies the thumb filter via Imagine, writes the result into web/media/cache/..., then serves it (typically via redirect). Subsequent hits skip Imagine entirely.

Where to look first: the bundle's Resources/config/ (services, routing, Twig extension) and its DependencyInjection/Configuration.php. Those three files tell you the real service IDs, the actual Twig filter name, the config root key, and the supported option shapes — all of which drift between forks. Do not trust blog posts written for the upstream bundle.

Best first use case: fixed-size thumbnails/avatars in a listing page. It is the lowest-risk, most obviously valuable filter, and it validates the whole pipeline (driver → route → cache dir → Twig) in one shot.

Implementation Patterns

Declarative filters, applied by name. Every transformation lives in config; templates only reference the name. This is the core value of the package — designers/devs don't hand-write Imagine code.

avalanche_imagine:
    filters:
        avatar:      { type: thumbnail,       options: { size: [64, 64],  mode: outbound } }
        hero:        { type: relative_resize, options: { widen: 1200 } }
        square:      { type: crop,            options: { start: [0, 0], size: [300, 300] } }
        rotated:     { type: rotate,          options: { angle: 90 } }
        branded:     { type: watermark,       options: { image: "%kernel.root_dir%/../web/logo.png", position: bottomright, x: 10, y: 10 } }

type maps to Imagine's FilterInterface implementations (thumbnail, resize, relative_resize, crop, rotate, paste, watermark, grayscale, strip, …). options is passed straight through as the Imagine option array, so the authoritative reference is Imagine's own docs, not this bundle's.

Multiple sizes from one source. Define thumb_sm, thumb_md, thumb_lg against the same original and switch in templates. This is the idiomatic pre-srcset approach and still works fine for fixed layouts.

Twig as the primary surface, PHP for everything else. In templates, pipe the raw relative path through the filter. When you need the URL outside a template (emails, JSON APIs, sitemaps), resolve the same route in PHP:

$url = $this->get('router')->generate('_imagine', [
    'path'   => 'images/photo.jpg',
    'filter' => 'thumb',
]);

Generating the URL is cheap; generation of the image only happens when that URL is requested.

Cache warming on deploy. Because generation is lazy and synchronous, the first visitor after a deploy eats the latency. Warm it: after cache:clear, iterate your known image list and curl (or file_get_contents) each _imagine URL, or drive the filter manager service directly:

$filter = $this->get('imagine.filter.manager')->get('thumb'); // verify service id
$image  = $this->get('imagine')->open($absolutePath);          // verify service id
$filter->apply($image)->save($cachePath);

Put this in a console command and run it as a deploy step.

Custom filters. For anything Imagine does not provide, implement Imagine's FilterInterface and register it with the filter manager through a service definition + a compiler pass or an explicit addFilter call in a bundle extension. This is the intended extension point; config filters remain the default path for 95% of needs.

Composition with Symfony assets. The filter returns a path, so wrap it in asset() if you version assets or serve from a CDN subdomain. Be aware that means the generated file must exist in whatever directory that CDN/origin publishes — the web_root + cache_prefix must match your deployment layout.

Gotchas and Tips

  • It is dead software. Last release 2016, one star, zero dependents. It predates Symfony 4 flex, autowiring and autoconfiguration; the bundle registration model alone will fail on modern Symfony. For any greenfield or upgradeable project use LiipImagineBundle (its direct successor, same Imagine engine, actively maintained). Only reach for this if you are pinned to a legacy app.
  • Verify names before coding. Fork drift is real: config root key (avalanche_imagine), Twig filter name (apply_filter vs imagine_filter), bundle class namespace, route name (_imagine), and service IDs can all differ from the upstream docs. Grep Resources/config/*.xml and DependencyInjection/Configuration.php first; half of all "it doesn't work" reports here are name mismatches.
  • The route is an open image proxy. It accepts path and filter from the URL. If the controller does not sanitize, you have path traversal / arbitrary file read (../../app/config/parameters.yml) and a CPU-exhaustion vector (anyone can request any filter against any path). Mitigate at the web-server level: only allow known filter names in the route requirement and deny .. segments; ideally restrict the source directory.
  • Writable cache directory. web/media/cache (or your cache_prefix) must exist and be writable by the PHP/web-server user. A permissions failure surfaces as a 500 on the image URL, not a friendly error — check var/logs//app/logs/.
  • Synchronous first-hit latency. A 4000px source run through a thumbnail filter can take hundreds of ms to seconds. Warm the cache on deploy, and avoid pointing a filter at a directory of large originals under load.
  • Two caches, and the wrong one gets cleared. cache:clear wipes Symfony's container cache but not web/media/cache. Change a filter's options and you will keep seeing the old output until you manually delete that directory. Make "clear the imagine cache" an explicit step whenever filter config changes.
  • Driver matters. gd is ubiquitous but lossy, memory-hungry on large images, and lacks some filters (quality/perf differ). imagick is usually better but must be installed and enabled; confirm with php -m. Setting driver to something unavailable fails at request time.
  • Options are Imagine's, not the bundle's. Wrong keys won't always error — they may be ignored silently, producing "unchanged" output that looks like a caching bug. thumbnail wants size + mode (inset/outbound); crop wants start + size; relative_resize wants widen/heighten/increase/scale, not width/height. Cross-check against the exact Imagine version in composer.lock.
  • Special characters in filenames. Paths with spaces, #, ? or non-ASCII must be URL-encoded before being routed through the filter; otherwise the generated URL 404s or the controller receives a truncated path. Prefer slugged filenames.
  • cache_prefix / web_root mismatch = 404s. The bundle writes to web_root + cache_prefix but the URL it returns is built from the same prefix. If your vhost document root, a symlinked current/ release, or a CDN origin points somewhere else, images generate successfully yet never resolve. Verify the physical file exists at the exact URL path when debugging. In capistrano-style deploys, make the cache dir a shared, symlinked path.
  • No invalidation, no garbage collection. Cached derivatives persist forever and are never pruned when originals change. Build a scheduled purge of media/cache (or keyed subdirectories) and delete derivatives when the source is replaced.
  • Debugging recipe: request the _imagine URL directly in the browser (not the <img>), watch for the redirect target, then confirm that file lands on disk. If the URL 404s, it's routing/config. If the file lands but the image is broken, it's the driver or filter options. If the file doesn't update, it's the media cache.
  • Prefer generating a URL through the router rather than string-concatenating /media/cache/{filter}/{path} — the prefix is configurable and your hand-built string will silently stop matching after a config change.
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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib