agence-adeliom/easy-media-bundle
Vue.js media manager for Symfony EasyAdmin with multi-upload, drag & drop, previews, image editing, bulk actions, visibility/locking, filters & sorting, directory bookmarks, URL embed support, keyboard shortcuts, and modal/WYSIWYG integration.
Installation
composer require agence-adeliom/easy-media-bundle
Add to config/bundles.php (Symfony) or config/packages/easy_media.yaml (Laravel via Symfony bridge):
AgenceAdeliom\EasyMediaBundle\EasyMediaBundle: []
Configure in EasyAdmin Extend your CRUD controller to use the media manager:
use AgenceAdeliom\EasyMediaBundle\EasyAdmin\Field\MediaField;
$crud->addField(MediaField::new('media')->setUploadDir('uploads/%year%/%month%/%day%'));
First Use Case
/admin/media to open the media manager.Media Assignment in EasyAdmin
MediaField in CRUD controllers for one-to-many/media relationships:
$crud->addField(MediaField::new('gallery')->setUploadDir('gallery/%year%')->allowMultiple());
Custom Upload Directories
$crud->addField(MediaField::new('avatar')->setUploadDir('avatars/%entity_id%'));
Integration with Forms
EasyMediaType form field for standalone media uploads:
$builder->add('media', EasyMediaType::class, [
'upload_dir' => 'documents/%year%',
]);
Media Preview & Metadata
# config/packages/easy_media.yaml
easy_media:
metadata_extractors:
- AgenceAdeliom\EasyMediaBundle\Metadata\Extractor\ImageExtractor
- AgenceAdeliom\EasyMediaBundle\Metadata\Extractor\AudioExtractor
Bulk Operations
Ctrl+Click + toolbar button).Laravel-Specific:
Use symfony/ux bridge to embed the Vue.js media manager in Laravel Blade:
@routes
@vite(['resources/js/app.js', 'node_modules/@symfony/ux-vue/dist/index.js'])
Mount the media manager route in routes/web.php:
use AgenceAdeliom\EasyMediaBundle\Controller\MediaController;
Route::prefix('admin')->group(function () {
Route::get('/media', [MediaController::class, 'index']);
});
EasyAdmin 4.x:
For newer EasyAdmin versions, wrap the field in EasyAdmin\Field\AssociationField for relationships:
$crud->addField(AssociationField::new('media')->setFormType(EasyMediaType::class));
Custom Metadata: Extend metadata extractors for niche formats (e.g., PDF thumbnails):
use AgenceAdeliom\EasyMediaBundle\Metadata\ExtractorInterface;
class PdfExtractor implements ExtractorInterface {
public function extract(string $path): array {
return ['thumbnail' => $this->generateThumbnail($path)];
}
}
File Naming Conflicts
setFilenameGenerator() to customize:
$crud->addField(MediaField::new('file')->setFilenameGenerator(
fn($file) => uniqid().'.'.$file->guessExtension()
));
Permission Issues
uploads/ directory is writable by the web server:
chmod -R 775 var/uploads
easy_media.yaml for cloud storage (e.g., S3):
easy_media:
storage: 'oneup_flysystem'
adapters:
local:
adapter: 'local'
options:
directory: '%kernel.project_dir%/public/uploads'
Vue.js Conflicts
@symfony/ux-vue is not bundled twice. Exclude in vite.config.js:
optimizeDeps.exclude.push('@symfony/ux-vue');
Metadata Extraction Failures
bin/console debug:metadata-extractors to verify registered extractors.easy_media:
metadata_extractors: []
Log Upload Paths:
Enable debug mode in easy_media.yaml:
easy_media:
debug: true
Check var/log/dev.log for resolved upload paths.
Broken Media Links:
Clear the cache after changing upload_dir:
php bin/console cache:clear
Custom File Types
Add MIME types to config/packages/easy_media.yaml:
easy_media:
allowed_mime_types: ['image/jpeg', 'image/png', 'application/pdf', 'video/mp4']
Override Templates
Copy templates/easy_media/ from the bundle to your project and modify (e.g., media_manager.html.twig).
API Endpoints Extend the media manager API for custom actions:
// src/Controller/MediaApiController.php
use AgenceAdeliom\EasyMediaBundle\Api\MediaApi;
class CustomMediaApi extends MediaApi {
public function customAction(): Response {
// ...
}
}
Route it in config/routes.yaml:
easy_media.api.custom:
path: /admin/media/custom
controller: App\Controller\MediaApiController::customAction
Event Listeners Hook into media events (e.g., post-upload):
use AgenceAdeliom\EasyMediaBundle\Event\MediaEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class MediaSubscriber implements EventSubscriberInterface {
public static function getSubscribedEvents() {
return [
MediaEvents::MEDIA_POST_UPLOAD => 'onMediaUpload',
];
}
public function onMediaUpload(MediaEvent $event) {
// $event->getMedia()->getPath();
}
}
How can I help you explore Laravel packages today?