Weave Code
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 Bundle Laravel Package

chamber-orchestra/image-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Bundle:

    composer require chamber-orchestra/image-bundle
    

    Add to config/bundles.php:

    return [
        // ...
        ChamberOrchestra\ImageBundle\ImageBundle::class => ['all' => true],
    ];
    
  2. Configure Basic Processing: Edit config/packages/chamber_orchestra_image.yaml (auto-generated on first run):

    chamber_orchestra_image:
        cache_dir: '%kernel.project_dir%/var/cache/image'
        processors:
            - fit
            - fill
        post_processors:
            - avifenc
        binaries:
            avifenc: '/usr/bin/avifenc'
            cwebp: '/usr/bin/cwebp'
    
  3. First Use Case: Resize an Image Use the Twig filter in a template:

    <img src="{{ image_url('path/to/image.jpg', 'thumb') }}">
    

    Define a filter in config/packages/chamber_orchestra_image.yaml:

    filters:
        thumb:
            width: 200
            height: 200
            fit: 'cover'
    

Implementation Patterns

Core Workflow: Image Processing Pipeline

  1. Define Filters: Configure filters in config/packages/chamber_orchestra_image.yaml under filters. Example:

    filters:
        avatar:
            width: 100
            height: 100
            fit: 'crop'
            crop: [50, 50, 100, 100] # [x1, y1, x2, y2]
        webp_conversion:
            post_processors: ['cwebp']
    
  2. Generate Signed URLs: Use the ImageUrlGenerator service in controllers:

    use ChamberOrchestra\ImageBundle\Service\ImageUrlGenerator;
    
    public function show(ImageUrlGenerator $urlGenerator, string $path, string $filter)
    {
        return new Response($urlGenerator->generate($path, $filter));
    }
    
  3. Async Processing with Messenger: Enable async processing in config:

    chamber_orchestra_image:
        async: true
    

    Trigger async processing via ImageProcessor:

    $processor = $this->container->get(ImageProcessor::class);
    $processor->processAsync($sourcePath, $filterName, $destinationPath);
    
  4. Twig Integration: Use built-in Twig filters:

    {# Generate URL #}
    {{ image_url('path/to/image.jpg', 'avatar') }}
    
    {# Generate HTML img tag #}
    {{ image_tag('path/to/image.jpg', 'avatar', { alt: 'User Avatar' }) }}
    

Integration Tips

  • Cache Management: Clear cache for specific filters:

    $cacheManager = $this->container->get(ImageCacheManager::class);
    $cacheManager->clearFilter('avatar');
    

    Or globally:

    php bin/console cache:clear
    
  • Custom Processors: Implement ProcessorInterface for custom logic (e.g., watermarking):

    class WatermarkProcessor implements ProcessorInterface
    {
        public function getIndexName(): string { return 'watermark'; }
    
        public function process(Imagine\Gd\Imagine $imagine, string $path): void
        {
            $watermark = $imagine->open('watermark.png');
            $size = $imagine->size();
            $imagine->paste($watermark, (int)($size->getWidth() * 0.8), (int)($size->getHeight() * 0.8));
        }
    }
    

    Register in config/packages/chamber_orchestra_image.yaml:

    processors:
        - watermark
    
  • Binary Paths: Use environment variables for binary paths (e.g., AVIFENC_PATH) and override in config:

    binaries:
        avifenc: '%env(AVIFENC_PATH)%'
    

Gotchas and Tips

Common Pitfalls

  1. Binary Dependencies:

    • Ensure required binaries (avifenc, cwebp, MozJPEG, pngquant) are installed and paths are correct. Test with:
      avifenc --version
      
    • Fallback: Disable post-processors in config if binaries are missing:
      post_processors: []
      
  2. Cache Invalidation:

    • Filters are cached per configuration. Changing a filter’s settings (e.g., width) requires clearing the cache:
      php bin/console chamber-orchestra:image:cache:clear
      
    • Async processing may leave stale cache entries. Use clearFilter() or clearAll() as needed.
  3. Async Processing Quirks:

    • Async jobs are dispatched via Messenger. Ensure the async config is true and the Messenger transport (e.g., Doctrine, Redis) is configured.
    • Debug async failures with:
      php bin/console messenger:consume async -vv
      
  4. HMAC-Signed URLs:

    • URLs expire if the ttl (time-to-live) in config is set too low. Default is 3600 (1 hour).
    • Regenerate URLs if the secret key changes (stored in IMAGE_SECRET env var).
  5. Image Source Paths:

    • Paths are relative to the public/ directory by default. Use absolute paths or configure a custom source_dir in config:
      source_dir: '%kernel.project_dir%/uploads'
      

Debugging Tips

  • Log Processor Output: Enable debug mode in config/packages/dev/chamber_orchestra_image.yaml:

    debug: true
    

    Logs will show processed paths and filter configurations.

  • Validate Filters: Use the validate command to check filter configurations:

    php bin/console chamber-orchestra:image:validate
    
  • Test Locally: Mock binaries for testing (e.g., symlink to dummy executables or use Docker containers with pre-installed tools).

Extension Points

  1. Custom Post-Processors: Extend AbstractPostProcessor for custom logic (e.g., adding metadata):

    class CustomPostProcessor extends AbstractPostProcessor
    {
        protected function getBinary(): string { return '/usr/bin/custom-tool'; }
    
        protected function getArguments(string $source, string $destination): array
        {
            return ['--metadata', $source, $destination];
        }
    }
    

    Register in config:

    post_processors:
        - custom
    
  2. Event Subscribers: Listen to ImageProcessedEvent for post-processing actions:

    use ChamberOrchestra\ImageBundle\Event\ImageProcessedEvent;
    use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
    
    #[AsEventListener(ImageProcessedEvent::class)]
    public function onImageProcessed(ImageProcessedEvent $event)
    {
        // Example: Log processed images
        $this->logger->info('Processed image', ['path' => $event->getPath()]);
    }
    
  3. Dynamic Filter Configuration: Override filter settings at runtime via the ImageFilterManager:

    $manager = $this->container->get(ImageFilterManager::class);
    $manager->setFilter('dynamic_thumb', [
        'width' => 300,
        'height' => 300,
    ]);
    
  4. Custom Cache Backend: Implement CacheInterface for alternative storage (e.g., S3):

    use ChamberOrchestra\ImageBundle\Model\CacheInterface;
    
    class S3Cache implements CacheInterface
    {
        public function save(string $path, string $content): void { /* ... */ }
        public function get(string $path): ?string { /* ... */ }
        public function delete(string $path): void { /* ... */ }
    }
    

    Bind in services.yaml:

    services:
        ChamberOrchestra\ImageBundle\Model\CacheInterface: '@app.s3_cache'
    

Configuration Quirks

  • Default Filter: Set a default_filter in config to apply to all images without a specified filter:

    default_filter: 'thumb'
    
  • Environment-Specific Configs: Use %env() placeholders for paths or secrets:

    cache_dir: '%env(IMAGE_CACHE_DIR)%'
    secret: '%env(IMAGE_SECRET)%'
    
  • Disable Processing: Set enabled: false to bypass all processing (useful for development):

    chamber_orchestra_image:
        enabled: false
    
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui