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

Webp Conversion Bundle Laravel Package

codebuds/webp-conversion-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require codebuds/webp-conversion-bundle
    

    Ensure your composer.json includes "require": {"php": "^8.1"} and Symfony 6.1+.

  2. Enable the Bundle Add to config/bundles.php:

    return [
        // ...
        Codebuds\WebPConversionBundle\WebPConversionBundle::class => ['all' => true],
    ];
    
  3. Basic Configuration Create config/packages/webp_conversion.yaml:

    web_p_conversion:
        upload_path: '%kernel.project_dir%/public/uploads'  # Default upload directory
        quality: 80  # Default WebP quality (0-100)
    
  4. First Use Case: Convert a Single Image Use the WebPConverter service in a controller or command:

    use Codebuds\WebPConversionBundle\Service\WebPConverter;
    
    class ImageController extends AbstractController
    {
        public function convert(Image $image): Response
        {
            $converter = $this->container->get(WebPConverter::class);
            $webpPath = $converter->convert($image->getPath(), $image->getExtension());
    
            return $this->json(['webp_path' => $webpPath]);
        }
    }
    

Implementation Patterns

Common Workflows

1. Automatic Conversion on Upload

Use Symfony’s EventSubscriber to trigger conversion after file uploads:

use Codebuds\WebPConversionBundle\Service\WebPConverter;
use Symfony\Component\HttpFoundation\File\UploadedFile;

class UploadSubscriber implements EventSubscriber
{
    public function __construct(private WebPConverter $converter) {}

    public function onUpload(UploadEvent $event): void
    {
        $file = $event->getFile();
        if ($file instanceof UploadedFile) {
            $webpPath = $this->converter->convert(
                $file->getPathname(),
                $file->guessExtension()
            );
            $event->setWebPPath($webpPath);
        }
    }
}

2. Batch Conversion (CLI)

Create a command to convert all images in a directory:

use Codebuds\WebPConversionBundle\Service\WebPConverter;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class ConvertAllCommand extends Command
{
    protected static $defaultName = 'app:convert-images';

    public function __construct(private WebPConverter $converter) {}

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $files = glob($this->getParameter('web_p_conversion.upload_path') . '/*.{jpg,jpeg,png,gif}');
        foreach ($files as $file) {
            $this->converter->convert($file, pathinfo($file, PATHINFO_EXTENSION));
            $output->writeln("Converted: $file");
        }
        return Command::SUCCESS;
    }
}

3. Dynamic Quality Adjustment

Override quality per image or request:

$webpPath = $converter->convert(
    $originalPath,
    $extension,
    ['quality' => 70]  // Override default quality
);

4. Integration with VichUploaderBundle

Extend VichUploaderStorage to generate WebP alongside original uploads:

use Codebuds\WebPConversionBundle\Service\WebPConverter;

class CustomStorage extends VichUploaderStorage
{
    public function __construct(
        private WebPConverter $converter,
        // ...
    ) {}

    public function updateFile($object, $file): void
    {
        parent::updateFile($object, $file);
        if ($file) {
            $webpPath = $this->converter->convert(
                $file->getPathname(),
                $file->guessExtension()
            );
            $object->setWebPPath($webpPath);
        }
    }
}

Integration Tips

  1. File System Configuration Ensure upload_path is writable and matches your storage setup (e.g., public/uploads for web-accessible files).

  2. Symfony Cache Clear cache after configuration changes:

    php bin/console cache:clear
    
  3. Environment-Specific Configs Use %kernel.environment% to define paths:

    web_p_conversion:
        upload_path: '%kernel.project_dir%/public/uploads/%kernel.environment%'
    
  4. WebP Fallback Serve WebP with <picture> tags in Twig:

    <picture>
        <source srcset="{{ asset(image.webPPath) }}" type="image/webp">
        <img src="{{ asset(image.originalPath) }}" alt="{{ image.alt }}">
    </picture>
    
  5. Queue Delayed Conversions Use Symfony Messenger to avoid blocking requests:

    $message = new ConvertImageMessage($originalPath, $extension);
    $this->messageBus->dispatch($message);
    

Gotchas and Tips

Pitfalls

  1. Extension Mismatch

    • Issue: The bundle only converts jpg, jpeg, png, and gif. Passing unsupported extensions (e.g., webp, svg) will fail silently or throw an error.
    • Fix: Validate extensions before conversion:
      $supportedExtensions = ['jpg', 'jpeg', 'png', 'gif'];
      if (!in_array(strtolower($extension), $supportedExtensions)) {
          throw new \InvalidArgumentException("Unsupported format: $extension");
      }
      
  2. Path Resolution

    • Issue: upload_path must be an absolute path (e.g., /var/www/uploads). Relative paths (e.g., ./uploads) will break.
    • Fix: Use %kernel.project_dir% for portability:
      upload_path: '%kernel.project_dir%/public/uploads'
      
  3. Quality vs. Size Tradeoff

    • Issue: High quality (e.g., 90) may not reduce file size significantly, while low quality (e.g., 50) can degrade visual fidelity.
    • Tip: Test with tools like WebP Playground to find the optimal balance.
  4. Overwriting Files

    • Issue: By default, the bundle overwrites existing WebP files with the same name. This can lead to data loss if not handled carefully.
    • Fix: Implement unique filenames or backup logic:
      $webpPath = $this->converter->convert(
          $originalPath,
          $extension,
          ['filename' => 'custom_' . uniqid() . '.webp']
      );
      
  5. GD vs. Imagick

    • Issue: The bundle relies on PHP’s GD library. If GD is missing or misconfigured, conversions will fail with cryptic errors.
    • Fix: Verify GD is installed:
      php -m | grep gd
      
      Enable Imagick as a fallback in webp_conversion.yaml:
      web_p_conversion:
          use_imagick: true  # Requires `pecl install imagick`
      

Debugging

  1. Enable Verbose Logging Add to config/packages/monolog.yaml:

    handlers:
        webp:
            type: stream
            path: '%kernel.logs_dir%/webp_conversion.log'
            level: debug
    
  2. Check Conversion Output Temporarily log the conversion process:

    $converter->convert($path, $extension, ['debug' => true]);
    
  3. Validate WebP Files Use file command to verify output:

    file /path/to/converted.webp  # Should output "WebP image data"
    

Extension Points

  1. Custom Filename Strategy Extend the converter to generate filenames dynamically:
    use Codebuds\WebPConversionBundle\Service\WebPConverterInterface;
    
    class CustomWebPConverter implements WebPConverterInterface
    {
        public function convert(string $originalPath, string $extension, array $options = []): string
        {
            $filename = $this->generateCustomFilename($originalPath, $options);
            // ... rest of the logic
        }
    
        private function generateCustomFilename(string $path, array $options): string
        {
            return 'custom_' . basename($path, '.' . $extension) . '_' . time() . '.webp';
        }
    }
    
    Register as a service:
    services:
        Codebuds\WebPConversionBundle\Service\WebPConverter:
            alias: 'app.custom
    
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.
anousss007/vigilance
supportpal/eloquent-model
ardenexal/fhir-models
laravel-at/laravel-image-sanitize
romalytar/yammi-audit-log-laravel
ardenexal/fhir-validation
arshaviras/weather-widget
laravel-chronicle/core
sunchayn/nimbus
daikazu/eloquent-salesforce-objects
unseen-codes/chat
romalytar/yammi-jobs-monitoring-laravel
kisame76/filament-db-table-state
nqxcode/laravel-lucene-search
dpfx/laravel-livewire-wizards
workos/workos-php-laravel
sofa/laravel-global-scope
nawasara/auth-primitives
adhocrat-io/arkhe-main
make-dev/orca-harpoon