Installation:
composer require awaresoft/sonata-media-bundle
If using the symlinked local version (as per README), ensure the /src/Awaresoft symlink exists and run:
php bin/console cache:clear
Enable the Bundle:
Add to config/bundles.php:
return [
// ...
Awaresoft\SonataMediaBundle\SonataMediaBundle::class => ['all' => true],
];
Basic Configuration:
Override the default config in config/packages/sonata_media.yaml:
sonata_media:
db_driver: doctrine_orm # or doctrine_mongodb
default_context: default
contexts:
default:
providers:
- sonata.media.provider.dailymotion
- sonata.media.provider.youtube
- sonata.media.provider.image
formats:
small: { width: 100 , quality: 70}
large: { width: 500 , quality: 70}
First Use Case: Upload an image via a form:
{{ form_start(form) }}
{{ form_widget(form.media) }}
<button type="submit">Upload</button>
{{ form_end(form) }}
Controller:
public function upload(Request $request, MediaManager $mediaManager) {
$media = $mediaManager->create();
$form = $this->createForm(MediaType::class, $media);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$mediaManager->save($media);
return new RedirectResponse($this->generateUrl('home'));
}
return $this->render('upload.html.twig', ['form' => $form->createView()]);
}
Provider Integration:
Extend existing providers (e.g., sonata.media.provider.image) or create custom ones:
// src/Provider/CustomProvider.php
class CustomProvider extends AbstractProvider {
public function generateUrl($media, $format = 'reference') { ... }
public function generateHttpResponse($media, $format = 'reference') { ... }
}
Register in config:
sonata_media:
contexts:
default:
providers:
- app.custom_provider
Form Handling:
Use MediaType for uploads or MediaGalleryType for multiple files:
$form = $this->createForm(MediaGalleryType::class, $media, [
'provider' => 'sonata.media.provider.image',
'context' => 'default',
]);
Twig Integration:
Use the sonata_media Twig extension:
{% set media = sonata_media.getMedia(1) %}
<img src="{{ sonata_media.getMediaUri(media, 'small') }}" alt="{{ media.name }}">
Or embed directly:
{{ sonata_media_embed(media, 'large') }}
Dynamic Formats: Generate thumbnails on-the-fly:
$url = $mediaManager->generatePublicUrl($media, 'large');
config/packages/sonata_admin.yaml:
sonata_admin:
templates:
layout: 'SonataMediaBundle::standard_layout.html.twig'
Create a media admin class:
class MediaAdmin extends AbstractMediaAdmin { ... }
use ApiPlatform\Core\Annotation\ApiResource;
use Sonata\MediaBundle\Entity\Media;
#[ApiResource]
class CustomMedia extends Media { ... }
Doctrine ORM/MongoDB:
Configure db_driver in sonata_media.yaml and ensure your Media entity extends Sonata\MediaBundle\Entity\Media.
Symfony UX Stimulus: Use Stimulus controllers for drag-and-drop uploads:
// assets/controllers/media_controller.js
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
connect() {
this.element.addEventListener('change', (e) => {
const files = e.target.files;
// Handle files via fetch API
});
}
}
Cloud Storage:
Use providers like sonata.media.provider.aws_s3 or sonata.media.provider.gcs for cloud storage.
Symlink Issues:
autoload_psr4.php is updated manually after changes.php bin/console cache:clear --env=prod --no-debug
Provider Conflicts:
sonata_media.yaml. Use unique keys (e.g., app.custom_provider).Media Entity Inheritance:
Sonata\MediaBundle\Entity\Media directly or use MediaHashed for hashed filenames:
use Sonata\MediaBundle\Entity\MediaHashed;
class CustomMedia extends MediaHashed { ... }
File Size Limits:
max_file_size in sonata_media.yaml to avoid upload failures:
sonata_media:
providers:
sonata.media.provider.image:
max_file_size: 10M
Twig Debugging:
{{ dump(sonata_media) }} to inspect available media and formats in Twig templates.Log Media Events: Enable debug mode and check logs for media-related errors:
php bin/console debug:config sonata_media
Provider Validation: Test providers in isolation:
$provider = $this->container->get('sonata.media.provider.image');
$media = $mediaManager->find(1);
$url = $provider->generateUrl($media, 'small');
Doctrine Events: Listen for media lifecycle events:
// src/EventListener/MediaListener.php
class MediaListener {
public function onMediaPrePersist(Media $media) {
// Custom logic before save
}
}
Register in services.yaml:
services:
App\EventListener\MediaListener:
tags:
- { name: doctrine.event_listener, event: prePersist }
Custom Media Types:
Extend MediaType to add custom fields:
class CustomMediaType extends MediaType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('custom_field', TextType::class);
}
}
Media Filters: Create custom filters for admin lists:
class CustomMediaFilter extends FilterForm {
protected function createQueryBuilder($queryBuilder, $alias, $field, $value) {
// Custom filtering logic
}
}
Media Events: Dispatch custom events:
$dispatcher->dispatch(new MediaEvent($media, 'custom.event'));
Listen in services:
services:
App\EventListener\CustomMediaListener:
tags:
- { name: kernel.event_listener, event: custom.event, method: onCustomEvent }
Media Metadata: Override metadata handling:
class CustomMediaManager extends MediaManager {
public function generatePublicUrl(MediaInterface $media, $format = 'reference') {
// Custom URL generation
}
}
Register as a service:
services:
sonata.media.manager.media:
class: App\Service\CustomMediaManager
How can I help you explore Laravel packages today?