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

Data Uri Bundle Laravel Package

1tomany/data-uri-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Install the bundle via Composer:

composer require 1tomany/data-uri-bundle

First Use Case: Embed a file (e.g., an image) directly in a Symfony API response as a Data URI.

  1. Create a DTO/Entity implementing OneToMany\DataUri\Contract\Record\DataUriInterface:

    use OneToMany\DataUri\Contract\Record\DataUriInterface;
    
    class ProductImage implements DataUriInterface
    {
        private string $path;
    
        public function __construct(string $path)
        {
            $this->path = $path;
        }
    
        public function getPath(): string
        {
            return $this->path;
        }
    }
    
  2. Use the Denormalizer in your API response (e.g., with API Platform or Symfony Serializer):

    use Symfony\Component\Serializer\Annotation\Context;
    
    class ProductDto
    {
        #[Context(['serializer_groups' => ['default']])]
        public ProductImage $image;
    }
    
  3. Test with the CLI Command (optional):

    php bin/console onetomany:data-uri:encode-file /path/to/image.png
    

Implementation Patterns

1. Serialization Workflow

  • Auto-Denormalization: The bundle auto-registers DataUriNormalizer for DataUriInterface. No manual configuration is needed for basic use.

  • Serializer Groups: Use @Context or #[Groups] to control when Data URIs are embedded:

    use Symfony\Component\Serializer\Annotation\Groups;
    
    class ProductDto
    {
        #[Groups(['api'])]
        public ProductImage $thumbnail;
    }
    
  • Custom Normalization: Extend DataUriNormalizer to add logic (e.g., size limits):

    use OneToMany\DataUriBundle\Serializer\DataUriNormalizer;
    
    class CustomDataUriNormalizer extends DataUriNormalizer
    {
        public function normalize($object, string $format = null, array $context = [])
        {
            if ($this->shouldSkip($object)) {
                return $object->getPath(); // Fallback to URL
            }
            return parent::normalize($object, $format, $context);
        }
    
        private function shouldSkip(DataUriInterface $uri): bool
        {
            $fileSize = filesize($uri->getPath());
            return $fileSize > 1_000_000; // Skip files >1MB
        }
    }
    

    Register it in config/services.yaml:

    services:
        App\Serializer\CustomDataUriNormalizer:
            tags: ['serializer.normalizer']
    

2. CLI Integration

  • Batch Encoding: Use the console command to pre-generate Data URIs for static assets:
    php bin/console onetomany:data-uri:encode-file assets/logo.png > logo.datauri
    
  • Scripting: Pipe output into templates or API responses:
    php bin/console onetomany:data-uri:encode-file assets/background.jpg | xargs -I{} echo "background-image: url({});" >> styles.css
    

3. File Source Patterns

  • Local Filesystem: Default behavior (e.g., /uploads/images/).
  • Cloud Storage: Use Flysystem adapters by extending DataUriInterface:
    use League\Flysystem\FilesystemOperator;
    
    class S3ProductImage implements DataUriInterface
    {
        private FilesystemOperator $filesystem;
        private string $path;
    
        public function __construct(FilesystemOperator $filesystem, string $path)
        {
            $this->filesystem = $filesystem;
            $this->path = $path;
        }
    
        public function getPath(): string
        {
            return $this->filesystem->readStream($this->path);
        }
    }
    

4. API Response Patterns

  • Embedded Assets: Return Data URIs in API responses for small files:
    {
        "product": {
            "name": "Widget",
            "thumbnail": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg..."
        }
    }
    
  • Conditional Embedding: Use a custom normalizer to switch between Data URIs and URLs based on context (e.g., ?embed=thumbnail):
    // In your controller
    $context = ['embed' => $request->query->get('embed')];
    return $this->serializer->serialize($dto, 'json', $context);
    

Gotchas and Tips

Pitfalls

  1. Large File Bloat:

    • Data URIs increase payload size by ~33% (base64 overhead). Avoid for files >1MB.
    • Fix: Implement a size-based fallback in your normalizer (see Custom Normalization above).
  2. File Path Security:

    • getPath() returns raw paths. Validate inputs to prevent:
      • Directory traversal attacks (e.g., ../../../etc/passwd).
      • Exposure of sensitive files.
    • Fix: Sanitize paths or use absolute paths:
      public function getPath(): string
      {
          return realpath($this->path) ?: $this->path;
      }
      
  3. Serializer Conflicts:

    • If another normalizer handles your object, the bundle’s DataUriNormalizer may be ignored.
    • Fix: Explicitly tag your normalizer with higher priority in config/services.yaml:
      tags: ['serializer.normalizer', { name: 'serializer.normalizer', priority: 100 }]
      
  4. Binary Data Corruption:

    • Improper handling of binary files (e.g., PDFs, ZIPs) can corrupt Data URIs.
    • Fix: Ensure getPath() returns a valid stream or binary-safe string.
  5. Non-Symfony Projects:

    • The bundle assumes Symfony’s DI and Serializer. For Laravel or other frameworks:
      • Use the underlying 1tomany/data-uri package directly.
      • Manually register the normalizer in your container.

Debugging Tips

  1. Check Normalizer Registration:

    • Verify the denormalizer is tagged correctly:
      php bin/console debug:container OneToMany\DataUriBundle\Serializer\DataUriNormalizer
      
    • Look for serializer.normalizer and serializer.denormalizer tags.
  2. Inspect Serialization Context:

    • Add debug context to see what’s being passed to the normalizer:
      #[Context(['debug' => true])]
      public ProductImage $image;
      
    • Check logs for debug context values.
  3. CLI Command Issues:

    • If onetomany:data-uri:encode-file fails:
      • Ensure the file path is absolute or resolvable.
      • Check file permissions (chmod -R 755 /path/to/files).
  4. Performance Bottlenecks:

    • Use Symfony’s profiler to measure encoding time:
      $event = new GetDataUriEvent($filePath);
      $this->dispatcher->dispatch($event, DataUriEvents::ENCODE);
      
    • Cache results if encoding is slow (e.g., with Symfony Cache component).

Extension Points

  1. Custom Data URI Formats:

    • Extend DataUriNormalizer to support custom MIME types or encoding options:
      public function normalize($object, string $format = null, array $context = [])
      {
          $mimeType = $context['mime_type'] ?? 'application/octet-stream';
          return 'data:' . $mimeType . ';base64,' . base64_encode(file_get_contents($object->getPath()));
      }
      
  2. Async Encoding:

    • Use Symfony Messenger to encode files asynchronously:
      use OneToMany\DataUri\Message\EncodeDataUriMessage;
      
      $bus->dispatch(new EncodeDataUriMessage($filePath));
      
    • Store results in a cache or database.
  3. Flysystem Integration:

    • Create a DataUriInterface adapter for cloud storage:
      class CloudDataUri implements DataUriInterface
      {
          private FilesystemOperator $filesystem;
          private string $path;
      
          public function getPath(): string
          {
              return $this->filesystem->readStream($this->path);
          }
      }
      
  4. Validation Rules:

    • Add constraints to DataUriInterface implementations:
      use Symfony\Component\Validator\Constraints as Assert;
      
      class ProductImage implements DataUriInterface
      {
          #[Assert\File(maxSize: '1M')]
          private string $path;
      }
      

Configuration Quirks

  1. No config/packages/ File Needed:

    • The bundle auto-configures. Avoid creating an empty data_uri.yaml—it’s unnecessary.
  2. Serializer Groups:

    • If using API Platform, ensure your `
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.
croct/coding-standard
croct/plug-php
nqxcode/phpmorphy
boundwize/pyrameter
testo/facade
develia/commons
dmstr/symfony-system-resources-bundle
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
renatomarinho/laravel-page-speed
develia/geo-bundle
austinheap/laravel-database-encryption
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
imbo/imbo-coding-standard
visualbuilder/filament-lottie
servicioslineaonce/starter-kit
atomcoder/laravel-reorderable
irajul/filament-shadcn-theme