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

Media Bundle Laravel Package

ano/media-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install Dependencies

    composer require ano/media-bundle knplabs/gaufrette avalanche123/imagine
    

    Ensure AnoSystemBundle is installed (or manually replicate its DIC utilities).

  2. Configure config.yml Add basic filesystem, CDN, and provider configurations:

    ano_media:
        filesystem:
            local:
                default: true
                id: ano_media.filesystem.local
                options:
                    base_path: "%kernel.root_dir%/../medias"
                    create: true
        cdn:
            local:
                default: true
                id: ano_media.cdn.remote_server
                options:
                    base_url: "http://img.example.com"
        provider:
            image:
                default: true
                id: ano_media.provider.image
        contexts:
            user_picture:
                formats:
                    small: { width: 50, height: 50 }
                    medium: { width: 90, height: 90 }
    
  3. Create a Base Media Model Extend Ano\Bundle\MediaBundle\Model\Media:

    namespace App\Model;
    use Ano\Bundle\MediaBundle\Model\Media as BaseMedia;
    
    abstract class Media extends BaseMedia {}
    
  4. Define a Context-Specific Model

    namespace App\Model;
    class UserPicture extends Media {
        protected $context = 'user_picture';
    }
    
  5. Use in a Form

    $form = $this->createFormBuilder($user)
        ->add('picture', FileType::class)
        ->getForm();
    
  6. Handle Upload in Controller

    $userPicture = new UserPicture();
    $userPicture->setContent($form->get('picture')->getData());
    $user->setPicture($userPicture);
    $em->persist($user);
    $em->flush();
    

First Use Case

Upload and generate thumbnails for a user avatar. The bundle automatically:

  • Stores the file in the configured filesystem.
  • Generates thumbnails per context (user_picture).
  • Serves files via CDN if configured.

Implementation Patterns

Core Workflows

  1. Context-Driven Media Handling

    • Define contexts in config.yml to group media types (e.g., user_picture, article_image).
    • Each context maps to a provider (e.g., image, video) and formats (e.g., thumbnails).
    • Example:
      contexts:
          article_image:
              formats:
                  thumbnail: { width: 200, height: 200 }
                  preview:   { width: 800, height: 600 }
      
  2. Provider Integration

    • Use ano_media.provider.image for images (requires Imagine).
    • Extend providers for custom logic (e.g., VideoProvider for metadata extraction).
    • Inject providers via dependency injection:
      class MyService {
          public function __construct(\Ano\Bundle\MediaBundle\Provider\ProviderInterface $imageProvider) {}
      }
      
  3. Filesystem Abstraction

    • Configure multiple filesystems (local, S3, etc.) in ano_media.filesystem.
    • Switch between them dynamically:
      filesystem:
          s3:
              id: ano_media.filesystem.s3
              options:
                  service: aws_s3
      
  4. ORM Integration

    • Use Single Table Inheritance (STI) for shared media tables.
    • Example UserPicture entity:
      class UserPicture extends Media {
          protected $context = 'user_picture';
      }
      
    • Doctrine mapping:
      <discriminator-map>
          <discriminator-mapping value="user_picture" class="App\Model\UserPicture" />
      </discriminator-map>
      
  5. Form Handling

    • Bind uploaded files to media objects:
      $media = new UserPicture();
      $media->setContent($request->files->get('picture'));
      
    • Use FileType in forms:
      $builder->add('image', FileType::class, [
          'mapped' => false, // MediaBundle handles persistence
      ]);
      
  6. CDN and URL Generation

    • Generate public URLs via the MediaManager:
      $url = $this->mediaManager->getUrl($media, 'small');
      
    • Configure CDN in ano_media.cdn:
      cdn:
          cloudfront:
              base_url: "https://cdn.example.com"
      

Integration Tips

  • Event Listeners: Extend media behavior via events (e.g., MediaPostUploadEvent).
  • Custom Providers: Create providers for unsupported media types (e.g., PdfProvider).
  • Validation: Use Symfony validators (e.g., File, MimeType) alongside media-specific rules.
  • Symfony Flex: If using Symfony 4+, manually register the bundle in config/bundles.php:
    return [
        // ...
        Ano\Bundle\MediaBundle\AnoMediaBundle::class => ['all' => true],
    ];
    

Gotchas and Tips

Pitfalls

  1. Missing AnoSystemBundle

    • If not installed, manually replicate remapParameters logic in MediaExtension.php:
      $loader->addRemapping('ano_media', '@AnoMediaBundle/Resources/config');
      
  2. Filesystem Permissions

    • Ensure base_path in ano_media.filesystem is writable:
      chmod -R 775 %kernel.root_dir%/../medias
      
  3. Context-Provider Mismatch

    • If thumbnails aren’t generated, verify:
      • The context (user_picture) exists in config.yml.
      • The provider (image) is enabled and configured.
      • The Imagine library is installed for image manipulation.
  4. STI Discriminator Conflicts

    • Avoid duplicate discriminator values in Doctrine mappings. Example:
      <!-- Wrong: Duplicate 'media' -->
      <discriminator-mapping value="media" class="App\Model\Media" />
      <discriminator-mapping value="media" class="App\Model\UserPicture" />
      
  5. CDN Caching Issues

    • Clear CDN cache after uploads if using external services (e.g., CloudFront).
    • Test locally with base_url: "http://localhost:8000/medias".
  6. Symfony 4+ Autowiring

    • Explicitly type-hint services to avoid autowiring conflicts:
      public function __construct(
          private MediaManagerInterface $mediaManager,
          private ProviderInterface $imageProvider
      ) {}
      

Debugging Tips

  • Log Media Events: Enable debug mode and check logs for MediaEvents:
    monolog:
        handlers:
            main:
                level: debug
    
  • Inspect Providers: Dump provider configurations:
    $provider = $this->container->get('ano_media.provider.image');
    var_dump($provider->getContexts());
    
  • Validate Config: Use Symfony’s config validator:
    php bin/console debug:config ano_media
    

Extension Points

  1. Custom Providers

    • Implement ProviderInterface and register in services.yml:
      services:
          app.media.provider.pdf:
              class: App\Provider\PdfProvider
              tags:
                  - { name: ano_media.provider, type: pdf }
      
  2. Event Subscribers

    • Listen to media events (e.g., MediaPostUploadEvent):
      class MySubscriber implements EventSubscriberInterface {
          public static function getSubscribedEvents() {
              return [
                  MediaEvents::POST_UPLOAD => 'onMediaUpload',
              ];
          }
          public function onMediaUpload(MediaPostUploadEvent $event) {
              // Custom logic (e.g., send notification)
          }
      }
      
  3. Dynamic Contexts

    • Load contexts dynamically via a compiler pass:
      class DynamicContextPass implements CompilerPassInterface {
          public function process(ContainerBuilder $container) {
              $contexts = $this->loadContextsFromDatabase();
              $container->setParameter('ano_media.contexts', $contexts);
          }
      }
      
  4. Override Default Services

    • Replace MediaManager or Filesystem implementations:
      services:
          ano_media.media_manager:
              class: App\Service\CustomMediaManager
              arguments: ['@ano_media.filesystem.local']
      
  5. Add Custom Metadata

    • Extend the Media base class to include fields like alt_text or copyright:
      class Media extends BaseMedia {
          protected $altText;
          // Getters/setters...
      }
      
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky