spatie/laravel-medialibrary
Attach and manage files on Eloquent models with an easy API. Handle uploads, store media on any Laravel filesystem (local, S3, etc.), organize collections, and generate image/PDF conversions and manipulations with built-in support for responsive images.
Installation:
composer require spatie/laravel-medialibrary
Publish the config and migrations:
php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="medialibrary-config"
php artisan migrate
Model Setup:
Use the HasMedia trait and RegistersMediaConversions trait in your Eloquent model:
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\MediaLibrary\RegistersMediaConversions;
class Post extends Model
{
use HasMedia, InteractsWithMedia, RegistersMediaConversions;
// ...
}
First Upload: Attach a file to a model in a controller or form handler:
$post = Post::find(1);
$post->addMedia($request->file('image'))->toMediaCollection('images');
default).thumbnails, documents).addMedia() with a UploadedFile from a request.Adding Media:
// From a file path
$model->addMedia($path)->toMediaCollection('collection_name');
// From a request file
$model->addMedia($request->file('file'))->toMediaCollection('collection_name');
// With custom disk (e.g., S3)
$model->addMedia($file)->toMediaCollection('collection_name', 's3');
Retrieving Media:
// Get first media in collection
$model->getFirstMedia('images');
// Get all media in collection
$model->getMedia('images');
// Get media URL
$model->getFirstMediaUrl('images');
// Get converted media (e.g., thumbnail)
$model->getFirstMedia('images')->getUrl('thumb');
Deleting Media:
// Delete single media
$model->getFirstMedia('images')->delete();
// Delete all media in collection
$model->clearMediaCollection('images');
Media Conversions:
Define conversions in registerMediaConversions():
protected function registerMediaConversions(Media $media = null): void
{
$this->addMediaConversion('thumb')
->width(100)
->height(100);
}
Use conversions:
$media->getUrl('thumb');
$media->getPath('thumb');
Custom Path Generators:
Override getPathGenerator() in your model or service provider:
public function getPathGenerator(): PathGenerator
{
return new CustomPathGenerator();
}
Temporary URLs: Generate time-limited URLs for private files:
$model->getFirstMedia('images')->getTemporaryUrl(60); // 60 seconds
Batch Operations:
Use Media model methods to query or manipulate media:
$media = Media::where('model_type', Post::class)
->where('model_id', 1)
->first();
Event Handling:
Listen for media events (e.g., MediaWasAdded, MediaWasDeleted) via Laravel events.
Form Requests: Validate file uploads using Laravel’s validation:
$request->validate([
'image' => 'required|image|mimes:jpeg,png,jpg|max:2048',
]);
API Responses:
Use toResponse() for API endpoints:
return $model->getFirstMedia('images')->toResponse();
Frontend Integration: Generate responsive images or thumbnails dynamically:
<img src="{{ $model->getFirstMediaUrl('images', 'thumb') }}" alt="Thumbnail">
Storage Optimization:
Use different disks for different media types (e.g., local for thumbnails, s3 for large files).
Missing Migrations:
Always run php artisan migrate after publishing the config. The media table is required.
Incorrect Collection Names:
Ensure collection names (e.g., 'images') match when adding/retrieving media. Typos will return null.
File Path Issues:
s3 disk with URL encoding disabled in Laravel’s filesystem config:
'disks' => [
's3' => [
'url' => env('AWS_URL'),
'encoding' => false, // Critical for S3
],
],
getAvailablePathRelativeToRoot().Conversion Failures:
imagick, ffmpeg, vips) for conversions.Orphaned Media:
Use php artisan media:clean to remove media no longer referenced by models. For large datasets, use the --hash flag for faster cleanup.
Memory Limits:
Large file conversions (e.g., PDFs, videos) may hit PHP memory limits. Adjust ini_set('memory_limit', '512M') or use deferred() conversions:
$this->addMediaConversion('thumb')->deferred();
Log Media Events: Temporarily add logging in event listeners to track media operations:
MediaWasAdded::class => function ($event) {
Log::debug('Media added:', ['model' => $event->model, 'media' => $event->media]);
},
Check Disk Config:
Verify disk configurations in config/filesystems.php match your storage setup.
Validate Media Existence:
Always check for null when retrieving media:
$media = $model->getFirstMedia('images');
if (!$media) {
// Handle missing media
}
Lazy Loading:
Use with() to eager-load media in queries:
$posts = Post::with('media')->get();
Batch Conversions: For bulk operations, defer conversions or use queue jobs:
$model->addMedia($file)->toMediaCollection('images')->deferred();
Cache Conversions: Cache converted media paths/URLs if conversions are expensive:
$media->getUrl('thumb', [], true); // Force cache
Custom Media Models:
Extend the Media model to add custom fields or behaviors:
class CustomMedia extends Media
{
protected $casts = [
'custom_field' => 'boolean',
];
}
Update the config to use your custom model.
Custom Conversions:
Create custom conversion classes by extending Spatie\MediaLibrary\Conversions\Conversion:
class CustomConversion extends Conversion
{
public function manipulate($image)
{
// Custom logic
}
}
Register it in registerMediaConversions().
Custom Path Generators:
Implement Spatie\MediaLibrary\PathGenerators\PathGenerator for unique path logic:
class CustomPathGenerator implements PathGenerator
{
public function getPath(Media $media): string
{
return "custom/{$media->model_type}/{$media->model_id}/{$media->name}";
}
}
Custom Thumbnails:
Use Laravel’s Image facade or libraries like Intervention Image for advanced manipulations:
$this->addMediaConversion('custom_thumb')
->width(200)
->height(200)
->manipulate(function ($image) {
$image->filter(new Vignette());
});
Default Disk:
Set the default disk in config/medialibrary.php:
'default_disk' => 's3',
Temporary URLs: Configure the expiration time and URL generation in the config:
'temporary_url_expiration' => 60, // seconds
FFmpeg Path:
If using video conversions, ensure the FFmpeg path is set in config/medialibrary.php:
'ffmpeg' => [
'binary' => '/usr
How can I help you explore Laravel packages today?