Installation
composer require development-x/media-bundle
Add to config/app.php under providers:
DevelopmentX\MediaBundle\MediaBundle::class,
Publish Configuration
php artisan vendor:publish --provider="DevelopmentX\MediaBundle\MediaBundle" --tag="config"
This generates config/media.php with default settings (e.g., storage paths, allowed MIME types).
First Use Case: Uploading a File
Create a form with enctype="multipart/form-data" and submit to a controller:
use DevelopmentX\MediaBundle\Services\MediaService;
public function upload(Request $request, MediaService $mediaService) {
$file = $request->file('file');
$media = $mediaService->upload($file, 'user_uploads'); // 'user_uploads' is a config key
return response()->json($media);
}
The MediaService handles validation, storage, and returns a Media object with metadata (path, URL, MIME type).
File Uploads with Validation
$media = $mediaService->upload($file, 'user_uploads', [
'allowed_mimes' => ['image/jpeg', 'image/png'],
'max_size' => 5 * 1024 * 1024, // 5MB
]);
config/media.php (e.g., user_uploads.allowed_mimes).InvalidArgumentException for invalid files.Associating Media with Entities
// In a User model
public function media() {
return $this->morphToMany(Media::class, 'model');
}
// Attach media to a user
$user->media()->attach($media->id);
Generating URLs
$media->url(); // Returns full URL (e.g., "/storage/user_uploads/123.jpg")
$media->thumbnailUrl('small'); // Generates thumbnail URL if configured.
Batch Processing
$mediaService->uploadMultiple($request->file('files'), 'user_uploads');
Media objects.Storage Systems: Configure config/media.php to use local, s3, or ftp drivers:
'disks' => [
'user_uploads' => [
'driver' => 's3',
'bucket' => 'my-bucket',
'key' => env('AWS_ACCESS_KEY_ID'),
],
],
Thumbnails: Enable via config/media.php:
'thumbnails' => [
'enabled' => true,
'paths' => [
'small' => 'thumbs/small',
'large' => 'thumbs/large',
],
],
Use MediaService::generateThumbnail() for custom sizes.
Events: Listen for upload events:
// In EventServiceProvider
protected $listen = [
'media.uploaded' => [MediaUploadedListener::class, 'handle'],
];
Missing Configuration
config/media.php is not published, the bundle throws RuntimeException on first use.php artisan vendor:publish --tag="config" after installation.Storage Permissions
storage/app/media. Ensure this directory is writable:
chmod -R 775 storage/app/media
.env and config.MIME Type Validation
finfo for MIME detection. If files are rejected unexpectedly:
config/media.php for allowed MIME types.$finfo = finfo_open(FILEINFO_MIME_TYPE);
echo finfo_file($finfo, $file->getPathname());
Polymorphic Relationships
media()->morphTo()) causes HasManyThrough errors.trait HasMedia {
public function media() {
return $this->morphToMany(Media::class, 'model');
}
}
Log Uploads
Enable logging in config/media.php:
'logging' => [
'enabled' => true,
'channel' => 'single',
],
Check storage/logs/laravel.log for upload events.
Validate File Paths
Use MediaService::getStoragePath() to debug paths:
$path = $mediaService->getStoragePath('user_uploads', $media->id);
Thumbnail Generation
imagemagick or graphicsmagick is installed (php -m | grep imagick).thumbnails.paths config points to a writable directory.Custom Storage Drivers
Implement DevelopmentX\MediaBundle\Contracts\StorageDriver:
class CustomDriver implements StorageDriver {
public function store(File $file, string $path) { ... }
public function url(string $path) { ... }
}
Register in config/media.php:
'drivers' => [
'custom' => \App\Services\CustomDriver::class,
],
Override Media Model
Extend DevelopmentX\MediaBundle\Models\Media to add custom fields:
class CustomMedia extends Media {
protected $casts = [
'alt_text' => 'string',
];
}
Bind the custom model in MediaBundleServiceProvider:
$this->app->bind(Media::class, CustomMedia::class);
Hooks for Post-Processing
Use the media.uploaded event to add custom logic (e.g., OCR, metadata extraction):
event(new MediaUploaded($media));
How can I help you explore Laravel packages today?