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

Livewire Media Selector Laravel Package

drpshtiwan/livewire-media-selector

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:
    composer require drpshtiwan/livewire-media-selector
    php artisan vendor:publish --tag=media-selector-config
    php artisan vendor:publish --tag=media-selector-migrations
    php artisan migrate
    php artisan storage:link
    
  2. Basic Usage: Add the component to a Blade view with a wire:model binding:
    <livewire:media-selector wire:model="media" collection="gallery" />
    
  3. Access the Modal: Trigger the modal via a button (e.g., using Livewire’s click event):
    <button wire:click="$emit('openMediaSelector')">Select Media</button>
    

First Use Case

User Profile Avatar Upload:

  • Use the collection="avatars" attribute to group media.
  • Bind the selected media to a user model’s avatar field:
    public $avatar;
    
  • In the Livewire component, handle the selection:
    public function updatedAvatar($value) {
        $this->user->update(['avatar' => $value]);
    }
    

Implementation Patterns

Core Workflows

  1. Media Selection:

    • Single Selection: Bind to a model field (e.g., wire:model="postImage").
    • Multiple Selection: Use wire:model="galleryImages" and ensure the parent model accepts an array.
    • Collections: Group media by feature (e.g., collection="product_gallery").
  2. Upload Handling:

    • Configure allowed extensions, max size, and disk in config/media-selector.php:
      'allowed_extensions' => ['jpg', 'png', 'gif'],
      'max_upload_kb' => 2048,
      'disk' => 'public',
      
    • Disable uploads per component:
      <livewire:media-selector :can-upload="false" />
      
  3. Model Integration:

    • Use the HasMediaSelector trait for Eloquent models:
      use Drpshtiwan\MediaSelector\Traits\HasMediaSelector;
      
      class Post extends Model {
          use HasMediaSelector;
      }
      
    • Attach media to a model:
      $post->attachMedia($mediaId, 'gallery');
      
    • Sync media (replace existing):
      $post->syncMedia($mediaIds, 'gallery');
      
  4. Event Listeners:

    • React to media events (e.g., uploads, deletions) via Livewire’s $dispatch or JavaScript:
      window.addEventListener('media-uploaded', (event) => {
          console.log('Uploaded:', event.detail);
      });
      

Integration Tips

  • Custom Styling: Publish views and override Tailwind classes:

    php artisan vendor:publish --tag=media-selector-views
    

    Modify resources/views/vendor/media-selector/....

  • Authorization: Use Livewire’s authorize method or Laravel Gates to restrict actions:

    public function authorizeDeleteMedia() {
        return auth()->user()->can('delete-media');
    }
    
  • Localization: Publish translations and extend:

    php artisan vendor:publish --tag=media-selector-lang
    

    Add custom language files to resources/lang/vendor/media-selector.

  • Performance:

    • Limit pagination per page (perPage attribute or config).
    • Use show-thumbnails="false" for large libraries to reduce render time.
  • Testing: Mock the Livewire component in PHPUnit:

    $this->livewire(MediaSelector::class)
         ->emit('openMediaSelector')
         ->assertSee('Media Selector');
    

Gotchas and Tips

Pitfalls

  1. Livewire Version Mismatch:

    • Ensure compatibility with Livewire 3.3+ or 4.x. Test thoroughly if upgrading/downgrading Livewire.
    • Fix: Check the changelog for breaking changes.
  2. Disk Configuration:

    • The public disk must be linked (php artisan storage:link). Missing symlinks cause "File not found" errors.
    • Fix: Verify disk paths in config/filesystems.php and run storage:link.
  3. Media Model Scope:

    • Actions (delete, restore) use scoped queries. Ensure your Media model’s scope* methods are correctly defined.
    • Fix: Override scopes in a custom Media model if needed:
      class Media extends \Drpshtiwan\MediaSelector\Models\Media {
          public function scopeForUser($query) {
              return $query->where('user_id', auth()->id());
          }
      }
      
  4. Thumbnail Generation:

    • Thumbnails are generated on-the-fly using Laravel’s Storage facade. Large images may cause timeouts.
    • Fix: Configure MEDIA_SELECTOR_THUMBNAIL_SIZE in config or use a queue for async generation.
  5. RTL Support:

    • Auto-detects RTL locales (e.g., Arabic), but custom CSS may override directions.
    • Fix: Add dir="rtl" to the modal container if needed.
  6. Event Dispatching:

    • Events like media-uploaded are dispatched via Livewire’s $dispatch. Ensure your frontend listens correctly.
    • Fix: Use wire:key to avoid event conflicts:
      <livewire:media-selector wire:key="'media-selector-{{ $id }}'" />
      
  7. Soft Deletes:

    • Trash functionality requires the SoftDeletes trait on the Media model. Ensure the migration includes deleted_at.
    • Fix: Run the published migration if missing:
      php artisan vendor:publish --tag=media-selector-migrations
      php artisan migrate
      

Debugging Tips

  • Log Upload Errors: Enable Livewire logging in config/livewire.php:

    'log' => env('LIVEWIRE_LOG', true),
    

    Check storage/logs/livewire.log for upload validation failures.

  • Inspect Payloads: Dump the wire:model payload to verify data structure:

    public function updatedMedia($value) {
        \Log::info('Selected media:', $value);
    }
    

    Expected format:

    ["path/to/file.jpg", "path/to/file.png"]
    
  • Check Disk Permissions: Verify the storage/app/public directory is writable:

    chmod -R 755 storage/app/public
    

Extension Points

  1. Custom Media Cards: Override the thumbnail template by publishing views and extending the media-card component:

    @extends('vendor.media-selector::media-card')
    @section('custom-content')
        <div class="custom-meta">{{ $media->size }} KB</div>
    @endsection
    
  2. Pluggable Uploads: Extend the UploadHandler class to add pre-upload logic (e.g., virus scanning):

    namespace App\Services;
    
    use Drpshtiwan\MediaSelector\Services\UploadHandler as BaseUploadHandler;
    
    class CustomUploadHandler extends BaseUploadHandler {
        public function validate($file) {
            parent::validate($file);
            // Add custom validation
        }
    }
    

    Bind the handler in config/media-selector.php:

    'upload_handler' => \App\Services\CustomUploadHandler::class,
    
  3. Dynamic Collections: Fetch collections dynamically via a Livewire property:

    public $collections = ['gallery', 'documents', 'avatars'];
    

    Bind to the component:

    <livewire:media-selector :collections="$collections" />
    
  4. Bulk Actions: Use Livewire’s $emit to trigger custom JavaScript for bulk operations:

    window.addEventListener('bulk-action', (event) => {
        const ids = event.detail.ids;
        // Call API for bulk delete/move
    });
    

    Dispatch from Livewire:

    $this->dispatch('bulk-action', ids: $selectedIds);
    
  5. Accessibility: Add ARIA labels or keyboard navigation by extending the modal template:

    <div class="modal" role="dialog" aria-label="Media Library">
        <!-- Content -->
    </div>
    

Configuration Quirks

  • show_thumbnails:

    • Set globally in config (MEDIA_SELECTOR_SHOW_THUMBNAILS = false).
    • Override per component with :show-thumbnails="false".
    • Note: Disabling thumbnails hides the preview section but keeps grid thumbnails.
  • can_upload:

    • Disables the entire Upload tab when
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.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle