drpshtiwan/livewire-media-selector
## Getting Started
### Minimal Setup
1. **Installation**
```bash
composer require drpshtiwan/livewire-media-selector
Publish the config:
php artisan vendor:publish --provider="Drpshtiwan\LivewireMediaSelector\ServiceProvider"
Basic Usage Add the component to your Blade view:
<livewire:media-selector />
Configure allowed disks and file types in config/livewire-media-selector.php:
'disks' => ['public', 's3'],
'allowed_mime_types' => ['image/jpeg', 'image/png', 'application/pdf'],
First Use Case Use the component to select a single image for a blog post:
<livewire:media-selector
wire:model="post.image"
:allowed-mime-types="['image/jpeg', 'image/png']"
:max-files="1"
/>
Single Media Selection Bind to a Livewire property:
<livewire:media-selector
wire:model="user.avatar"
:allowed-mime-types="['image/*']"
/>
Access selected media in your Livewire component:
public $avatar;
public function mount()
{
$this->avatar = $this->user->avatar ?? null;
}
Multiple Media Selection
<livewire:media-selector
wire:model="gallery.images"
:allowed-mime-types="['image/*']"
:max-files="10"
multiple
/>
Custom Storage Integration
Extend the MediaSelector class to add custom logic:
use Drpshtiwan\LivewireMediaSelector\MediaSelector;
class CustomMediaSelector extends MediaSelector
{
public function getMedia()
{
$media = parent::getMedia();
return $media->filter(fn ($item) => $item->is_public);
}
}
Integration with File Uploads
Use the upload event to process files after selection:
<livewire:media-selector
@upload="processUpload($event)"
/>
Dynamic Configuration Pass dynamic config via props:
<livewire:media-selector
:disks="['public', 'private']"
:allowed-mime-types="['image/*', 'video/*']"
:max-file-size="5" // in MB
/>
Custom Thumbnail Generation
Override the getThumbnailUrl method in a custom component:
public function getThumbnailUrl($media)
{
return Storage::disk('public')->url("custom/thumbs/{$media->path}");
}
Media Metadata Handling
Use the media-selected event to process metadata:
<livewire:media-selector
@media-selected="handleMediaSelection($event)"
/>
public function handleMediaSelection($event)
{
$this->processMedia($event->media);
}
Bulk Operations Implement bulk actions (e.g., delete) via custom props:
<livewire:media-selector
:selected-media="old('selected_media', [])"
@bulk-delete="deleteSelectedMedia"
/>
File Size Limits
max-file-size in config matches your server’s upload_max_filesize and post_max_size in php.ini.5MB; adjust in config or via props:
'max_file_size' => 10, // MB
Disk Permissions
php artisan storage:link
.env.CORS Issues
<CORSConfiguration>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>
Livewire Property Binding
string for file paths, array for multiple files).public $image; // For single file
public $images = []; // For multiple files
Media Not Updating
php artisan cache:clear
php artisan view:clear
wire:model is correctly bound to a public property.Log Media Queries Temporarily enable debug mode in config:
'debug' => true,
Check logs for SQL queries or disk operations.
Check Disk Contents Verify files exist on the disk:
ls storage/app/public
Validate MIME Types
Use dd($event->media->mime_type) in the media-selected event to debug MIME type issues.
Livewire Wire:Key Conflicts
If using multiple instances, ensure unique wire:key:
<livewire:media-selector wire:key="'selector-1'" />
Custom Media Models
Extend the Media model to add custom fields:
use Drpshtiwan\LivewireMediaSelector\Models\Media;
class CustomMedia extends Media
{
protected $casts = [
'alt_text' => 'string',
'custom_metadata' => 'json',
];
}
Override Media Listing Replace the default media listing logic:
public function getMedia()
{
return CustomMedia::query()
->where('user_id', auth()->id())
->get();
}
Add Custom Tabs Extend the component to include additional tabs (e.g., "Collections"):
<livewire:media-selector>
<x-slot name="tabs">
<x-media-selector.tab name="collections">Collections</x-media-selector.tab>
</x-slot>
</livewire:media-selector>
Localization Override default labels in your Blade view:
<livewire:media-selector>
<x-slot name="labels">
<x-media-selector.label upload="Upload Custom Label" />
</x-slot>
</livewire:media-selector>
Event Customization
Listen to internal events (e.g., media-uploading):
<livewire:media-selector
@media-uploading="logUploadEvent($event)"
/>
Lazy Loading Use pagination for large media libraries:
public function getMedia()
{
return CustomMedia::query()->paginate(20);
}
Thumbnail Optimization Generate thumbnails asynchronously using queues:
public function handleMediaSelection($event)
{
GenerateThumbnailJob::dispatch($event->media);
}
Caching Cache media listings if they rarely change:
public function getMedia()
{
return Cache::remember('media-list', now()->addHours(1), function () {
return CustomMedia::all();
});
}
Disk Indexing
For large disks, implement a database index for path or filename in the media table.
```markdown
## Configuration Deep Dive
### Key Config Options
| Option | Default | Description |
|----------------------|----------------------------------|-----------------------------------------------------------------------------|
| `disks` | `['public']` | Array of storage disks to scan. |
| `allowed_mime_types` | `['image/*']` | MIME types allowed for uploads. |
| `max_file_size` | `5` (MB) | Maximum file size in MB. |
| `max_files` | `null` | Maximum files to select (use `0` for unlimited). |
| `thumbnail_size` | `['width' => 150, 'height' => 150]| Thumbnail dimensions. |
| `sort_by` | `'created_at desc'` | Default sorting for media listings. |
| `debug` | `false` | Enable debug logging. |
### Environment-Specific Config
Override config per environment in `.env`:
```env
How can I help you explore Laravel packages today?