Installation
composer require deusz/media-bundle
Add to config/bundles.php:
return [
// ...
Deusz\MediaBundle\DeuszMediaBundle::class => ['all' => true],
];
Database Migration Run the bundle’s migrations:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
First Media Upload
Configure a provider (e.g., sonata.media.provider.local for filesystem storage) in config/packages/deusz_media.yaml:
deusz_media:
providers:
local:
filesystem: '%kernel.project_dir%/public/uploads'
Use in a controller:
use Deusz\MediaBundle\Model\MediaInterface;
use Deusz\MediaBundle\Model\MediaManagerInterface;
public function uploadMedia(MediaManagerInterface $mediaManager)
{
$media = $mediaManager->create();
$media->setProviderName('local');
$media->setContext('default');
$media->setEnabled(true);
// Handle file upload (e.g., from a request)
$file = $request->files->get('file');
$media->setBinaryContent($file->getContent());
$media->setOriginalFilename($file->getClientOriginalName());
$mediaManager->save($media);
return $media;
}
Display Media
Use the Media entity in templates:
{% for media in medias %}
<img src="{{ media.thumbnail('media_default') }}" alt="{{ media.name }}">
{% endfor %}
Provider-Specific Logic: Extend MediaProviderInterface for custom storage (e.g., S3, Cloudinary).
namespace App\Media\Provider;
use Deusz\MediaBundle\Model\MediaInterface;
use Deusz\MediaBundle\Model\MediaProviderInterface;
class CustomProvider implements MediaProviderInterface
{
public function generatePublicUrl(MediaInterface $media, $format = null)
{
return "https://custom-cdn.com/{$media->getId()}.{$format}";
}
}
Register in deusz_media.yaml:
deusz_media:
providers:
custom:
class: App\Media\Provider\CustomProvider
Binary Handling: Use MediaManager to process files:
$mediaManager->generateMedia($media, 'media_thumbnail', 'sonata.media.generator.thumbnail');
MediaType for Symfony forms:
use Deusz\MediaBundle\Form\Type\MediaType;
$builder->add('media', MediaType::class, [
'provider_name' => 'local',
'context' => 'default',
'multiple' => true,
]);
MediaRepository for filtering:
$media = $mediaRepository->findBy([
'context' => 'default',
'enabled' => true,
]);
config/packages/deusz_media.yaml:
deusz_media:
generators:
thumbnail:
service: sonata.media.generator.thumbnail
extension: gif
options:
size: [100, 100]
quality: 90
Generate in code:
$mediaManager->generateMedia($media, 'media_thumbnail', 'thumbnail');
products, blogs):
$media->setContext('products');
Event Listeners: Subscribe to MediaEvents for post-upload actions:
use Deusz\MediaBundle\Event\MediaEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class MediaSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
MediaEvent::POST_UPLOAD => 'onMediaUpload',
];
}
public function onMediaUpload(MediaEvent $event)
{
$media = $event->getMedia();
// Add custom logic (e.g., log, notify)
}
}
API Responses: Serialize media for APIs:
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
$serializer->normalize($media, 'json', [
'groups' => ['media_read'],
]);
Caching: Cache generated thumbnails with sonata.media.cache.generic service.
Provider Configuration
provider_name on a Media entity causes MediaManager::save() to fail.provider_name exists in deusz_media.yaml:
if (!$media->getProviderName() || !$mediaManager->hasProvider($media->getProviderName())) {
throw new \InvalidArgumentException('Invalid provider');
}
File Permissions
public/uploads is writable:
chmod -R 775 public/uploads
Generator Dependencies
sonata.media.generator.thumbnail service breaks thumbnail generation.sonata-media-bundle or manually define generators:
services:
sonata.media.generator.thumbnail:
class: Sonata\MediaBundle\Generator\Generator
arguments:
- sonata.media.generator.thumbnail
Binary Content vs. Filesystem
setBinaryContent() (in-memory) with filesystem paths.setBinaryContent() for direct uploads; setPath() for filesystem-based providers.Context Mismatches
MediaRepository:
$media->setContext('valid_context'); // Ensure this matches your app's contexts.
Enable Debug Mode: Add to deusz_media.yaml:
deusz_media:
debug: true
Logs provider calls and generator execution.
Check Events: Dump dispatched events:
$dispatcher->addListener(MediaEvent::PRE_UPLOAD, function (MediaEvent $event) {
error_log('Media upload event: ' . print_r($event->getMedia(), true));
});
Validate Entities: Use Symfony’s validator:
$errors = $validator->validate($media);
if (count($errors) > 0) {
throw new \RuntimeException((string) $errors);
}
Custom Providers
MediaProviderInterface for cloud storage (e.g., AWS S3, Google Cloud Storage).generatePublicUrl() and delete() methods.Media Metadata
Media entity:
/**
* @ORM\Column(type="string", nullable=true)
*/
private $customMetadata;
Generator Services
services:
app.media.generator.pdf_thumbnail:
class: App\Media\Generator\PdfThumbnailGenerator
tags:
- { name: sonata.media.generator, type: pdf_thumbnail }
Security
$voter = new MediaVoter();
$voter->supportsClass(Media::class) && $voter->vote($token, $media, ['READ']);
Batch Processing
MediaManager in bulk:
foreach ($mediaList as $media) {
$mediaManager->generateMedia($media, 'media_thumbnail', 'thumbnail');
}
How can I help you explore Laravel packages today?