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

app-verk/media-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require app-verk/media-bundle
    

    Ensure app-verk/components (v2.0+) is also installed.

  2. Register the Bundle Add to config/bundles.php (Laravel 5.4+) or AppKernel.php:

    AppVerk\MediaBundle\MediaBundle::class => ['all' => true],
    
  3. Create a Media Entity Extend BaseMedia in app/Models (Laravel) or src/Entity (Symfony):

    namespace App\Models;
    
    use AppVerk\MediaBundle\Entity\Media as BaseMedia;
    use Illuminate\Database\Eloquent\Model;
    
    class Media extends BaseMedia {}
    
  4. Configure Add to config/media.php (Laravel) or config.yml (Symfony):

    media:
        entities:
            media_class: App\Models\Media
        allowed_mime_types: ["image/jpeg", "image/png", "application/pdf"]
    
  5. Publish Assets

    php artisan vendor:publish --tag=media-assets
    

    Include in your layout:

    <link href="{{ asset('vendor/media/css/dropzone.min.css') }}" rel="stylesheet">
    <script src="{{ asset('vendor/media/js/dropzone.min.js') }}"></script>
    
  6. Run Migrations

    php artisan migrate
    

First Use Case: Uploading an Image

  1. Create a Form

    use AppVerk\MediaBundle\Form\Type\MediaType;
    
    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder->add('image', MediaType::class);
    }
    
  2. Render in Blade/Twig

    <img src="{{ $post->image->url }}" alt="Post Image">
    

Implementation Patterns

Core Workflows

1. File Upload with Dropzone

  • Frontend Integration: Use the provided Dropzone.js wrapper. Initialize with:
    Dropzone.autoDiscover = false;
    new Dropzone("#dropzone", {
        url: "{{ route('media_upload') }}",
        maxFilesize: {{ config('media.max_file_size') / 1024 }}, // in MB
        acceptedFiles: "{{ implode(',', config('media.allowed_mime_types')) }}",
    });
    
  • Backend Handling: The bundle auto-generates routes for uploads (/media/upload). No manual controller needed.

2. Entity Relationships

  • One-to-Many:
    // Post.php
    public function media() {
        return $this->morphToMany(Media::class, 'model');
    }
    
  • Polymorphic Uploads: Use morphToMany with model and model_type columns in the media table.

3. Validation Groups

  • Config:
    media:
        groups:
            documents:
                allowed_mime_types: ["application/pdf", "application/msword"]
                max_file_size: 10000000
    
  • Form Usage:
    $builder->add('document', MediaType::class, [
        'group' => 'documents',
        'label' => 'Upload Document',
    ]);
    

4. Customizing Storage

  • Override Storage Path:
    media:
        storage_path: 'storage/custom_media'
    
  • Use Cloud Storage: Extend the Media entity to override getUrl():
    public function getUrl() {
        return Storage::disk('s3')->url($this->path);
    }
    

5. Bulk Uploads

  • API Endpoint: Create a controller to handle bulk uploads:
    public function bulkUpload(Request $request) {
        $validator = Validator::make($request->all(), [
            'files.*' => 'required|file',
        ]);
        if ($validator->fails()) return response()->json(['error' => $validator->errors()]);
    
        foreach ($request->file('files') as $file) {
            $media = new Media();
            $media->upload($file);
            $media->save();
        }
        return response()->json(['success' => true]);
    }
    

Integration Tips

Laravel-Specific Adjustments

  1. Service Provider: Register the bundle in AppServiceProvider:

    public function boot() {
        $this->loadViewsFrom(__DIR__.'/../../vendor/app-verk/media-bundle/Resources/views', 'media');
    }
    
  2. Blade Directives: Add a helper for Twig-like syntax:

    Blade::directive('media', function ($expression) {
        return "<?php echo app('media')->getUrl($expression); ?>";
    });
    

    Usage:

    <img src="@media($post->image)">
    
  3. Form Integration: Use Laravel Collective for forms:

    use AppVerk\MediaBundle\Form\MediaType;
    
    $form->add('thumbnail', MediaType::class, [
        'attr' => ['class' => 'dropzone'],
    ]);
    

Symfony-Specific Adjustments

  1. Twig Extensions: Register the Twig extension in services.yml:

    services:
        media.twig.extension:
            class: AppVerk\MediaBundle\Twig\MediaExtension
            tags: ['twig.extension']
    
  2. Event Listeners: Listen for upload events:

    public function onMediaUpload(MediaEvent $event) {
        if ($event->getMedia()->getMimeType() === 'image/jpeg') {
            // Process JPEG specifically
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Dropzone.js Conflicts:

    • Issue: Dropzone may conflict with other JS libraries (e.g., jQuery UI).
    • Fix: Initialize Dropzone after DOM is ready and isolate its scope:
      $(document).ready(function() {
          new Dropzone("#dropzone", { /* options */ });
      });
      
  2. Mime Type Validation:

    • Issue: Browser-based validation may not catch all server-side rules (e.g., max_file_size).
    • Fix: Always validate on the server. Use the group config to enforce rules per field.
  3. Polymorphic Relationships:

    • Issue: Forgetting to set model_type and model_id can break queries.
    • Fix: Use Laravel’s morphToMany or manually set:
      $media->model()->associate($post);
      $media->model_type = (new ReflectionClass($post))->getShortName();
      
  4. Storage Permissions:

    • Issue: Uploads fail silently if the storage_path lacks write permissions.
    • Fix: Ensure the directory exists and is writable:
      mkdir -p storage/custom_media && chmod -R 775 storage/custom_media
      
  5. Deprecated Methods:

    • Issue: The bundle uses Symfony’s FormBuilder, which may not work seamlessly in Laravel.
    • Fix: Use Laravel’s Form facade or wrap the bundle’s form types:
      use AppVerk\MediaBundle\Form\MediaType as BaseMediaType;
      
      class MediaType extends BaseMediaType {
          public function buildForm(FormBuilder $builder, array $options) {
              parent::buildForm($builder, $options);
              // Laravel-specific adjustments
          }
      }
      

Debugging Tips

  1. Log Upload Errors: Add a listener to log failed uploads:

    public function onMediaUploadFailed(MediaEvent $event) {
        \Log::error('Media upload failed', [
            'message' => $event->getError(),
            'file' => $event->getFile()->getClientOriginalName(),
        ]);
    }
    
  2. Check Mime Types: Verify mime types with:

    $mime = mime_content_type($file->getPathname());
    \Log::info("Detected mime type: $mime");
    
  3. Validate Config: Ensure media_class in config/media.php matches your extended Media class exactly (namespace included).

Extension Points

  1. Custom Validators: Extend the validator by overriding the Media entity’s validate() method:

    public function validate($group = null) {
        $validator = parent::validate($group);
        $validator->add('width', 'numeric', ['min' => 100]);
        return $validator;
    }
    
  2. Post-Upload Processing: Use events to process files after upload:

    public function onMediaUploaded(MediaEvent $event) {
        $media = $event->getMedia();
        if ($media->getMimeType
    
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
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