symfony-cmf/media-bundle
Symfony CMF Media Bundle adds media management to Symfony CMF apps: upload, browse, edit, and organize images and documents with PHPCR-backed storage and integration into the CMF content framework.
First, the reality check: symfony-cmf/media-bundle is a Symfony bundle (namespace Symfony\Cmf\Bundle\MediaBundle), not a Laravel package. There is no service provider, no facade, no config/app.php entry, and no artisan command. It registers itself through CmfMediaBundle in a Symfony kernel and hard-depends on doctrine/phpcr-odm, symfony/framework-bundle, symfony/form, and liip/imagine-bundle for image work. You cannot composer require it into a Laravel app and have it behave like a normal Laravel dependency — the PHPCR storage, form upload integration, and image variation pipeline all assume an HttpKernel + Doctrine bundle lifecycle that Illuminate does not provide.
That leaves two realistic entry points for a Laravel developer:
Minimal steps for scenario 2:
composer require symfony-cmf/media-bundle:^1.3 liip/liip-imagine-bundle doctrine/phpcr-odm doctrine/phpcr-bundle jackalope/jackalope-doctrine-dbalCmfMediaBundle, DoctrinePhpcrBundle, LiipImagineBundle in app/AppKernel.php.cmf_media extension: media_manager.media_basepath: /cms/media, a media_class (e.g. …\Doctrine\Phpcr\Image), plus a doctrine_phpcr session. Run bin/console doctrine:phpcr:init.UploadFileHelper to persist a File/Image document, then ask the configured Imagine thumbnail generator for a named variation and hand back a public URL.Where to look first in the source:
DependencyInjection/Configuration.php — the authoritative config tree (media_manager, thumbnail_generators, upload_file_helper, etc.).Resources/config/*.xml — real service IDs: cmf_media.manager, cmf_media.upload_file_helper, and the cmf_media.thumbnail_generator.* implementations.Model/MediaInterface.php and Model/ImageInterface.php — the contracts your application code should type against.Doctrine/Phpcr/MediaManager.php — the API you'll actually call every day.Talk to the manager, not the documents. Inject cmf_media.manager (MediaManagerInterface) and use createMedia(), findMediaById(), getUrlSafeFilename(), getMediaBasepath(). Resolving PHPCR nodes directly couples you to node paths, which is exactly what breaks on upgrade and what makes the bundle feel "fragile" when it isn't.
Uploads are Symfony UploadedFile territory. UploadFileHelper expects Symfony\Component\HttpFoundation\File\UploadedFile and pulls the request from RequestStack. On the Symfony side you bind this through a form; from Laravel you're calling a Symfony controller endpoint with a multipart body, so keep that controller thin — take the UploadedFile, delegate to the helper, return {id, url, mime, size}.
Image variations via configuration, not code. Declare filter sets once under the thumbnail/Imagine config, then reference them by name in templates or in a ?variation=thumb query param. The bundle's cache resolver writes variations under the Imagine cache directory. Don't hand-roll Imagine filters in application code — you bypass the cache resolver and regenerate on every request.
Extending media types. Subclass Doctrine\Phpcr\File or Image, add fields, and point media_manager.media_class (or the per-class mapping) at your class. Wire the extra fields into Sonata admin if editors need them. This is the intended extension seam — resist adding logic to MediaManager itself.
Laravel-side pattern (the realistic one). Store only the Symfony media ID (a PHPCR UUID/path string), the resolved public URL, mime type, dimensions, and a variation_version in MySQL. Create on upload, cache the returned metadata on save, and render pages by reading the cached URL — never call the Symfony service at render time. Treat the media service like an asset store, not a runtime dependency; the moment it becomes a synchronous render-time call, you've added a single point of failure to every page.
Content references. Symfony CMF content documents hold PHPCR ODM references to MediaInterface. On the Laravel side, mirror that as a media_id column behind a small MediaReference value object, so the two storage systems never share a raw ID type.
jackalope-doctrine-dbal lets you run on MySQL but is slower, has edge cases around references and node moves, and its own maintenance is thin. If you don't already operate PHPCR, the storage layer is the cost — not the media manager.media_basepath vs. web path. Media lives under a logical basepath (/cms/media) that must be mapped to a web-served directory. The classic "thumbnails 404" bug is a mismatch here, or a missing/unwritable Imagine cache directory. Check those before blaming the bundle.HttpFoundation lifecycles and two service containers. The only sustainable integration is an HTTP boundary or a shared PHPCR-backed data tier.MediaManager, and use the manager's pre/post-save hooks (or a decorator) for side effects. When you eventually replace this bundle, a decorator drops out cleanly; a subclass drags half the class with it.phpcr_odm and cmf_media channels. bin/console doctrine:phpcr:node:dump on the media root is faster than var_dump inside a controller, and it shows you whether the failure is at persist time or at document-creation time.bin/console liip:imagine:cache:remove, and bump the variation_version you cache in Laravel. Otherwise Laravel keeps serving stale URLs to variations that no longer exist.bin/console config:dump-reference cmf_media disagrees with the docs, believe the console — that's the tree the extension actually loads.^1.3.1 so later (hypothetical) patches land — but accept that there almost certainly won't be any.How can I help you explore Laravel packages today?