Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Media Bundle Laravel Package

kunstmaan/media-bundle

KunstmaanMediaBundle adds media management to Symfony CMS applications, letting editors upload, organize, and store images and files through an admin interface. It includes thumbnail generation, media folders, and integration with the Kunstmaan admin bundle for managing assets across your site.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first. kunstmaan/media-bundle is a Symfony 2.x-era bundle, not a Laravel package. It has no service provider, no config publish tag, and its entities are Doctrine ORM classes with annotations. You cannot composer require it into a Laravel app and get anything useful. Its day-to-day value is: (a) if you maintain a legacy Kunstmaan Bundles CMS project, or (b) as a reference architecture you port into Laravel. The 38 stars are misleading — this is a split-out sub-bundle of Kunstmaan/KunstmaanBundlesCMS, where the real community lives.

Minimal install (Symfony 2.x/3.x host).

  1. composer require kunstmaan/media-bundle — but check composer.json first; the 2014 release pins Symfony 2.3–2.7-era constraints and PHP 5.x. Expect dependency hell on anything modern.
  2. Register the bundle in AppKernel: new Kunstmaan\MediaBundle\KunstmaanMediaBundle(),
  3. Import routing with an admin prefix:
    kunstmaan_media:
        resource: "@KunstmaanMediaBundle/Resources/config/routing.yml"
        prefix: /admin/media
    
  4. Configure (dump the real reference with bin/console config:dump-reference kunstmaan_media — keys drift between versions):
    kunstmaan_media:
        aviary_api_key: "%aviary_key%"      # see gotchas: this is dead
        use_symfony_file_storage: true
        # remote_video / soundcloud keys exist in some versions
    
  5. Update the schema (doctrine:schema:update or a migration) — you need at least the media and folder tables.
  6. assets:install --symlink for the media chooser JS/CSS, plus LiipImagineBundle config for your filter sets.

Where to look first, in this order:

  • Entity/Media.php and Entity/Folder.php — the actual data model (name, contentType, location, url, metadata JSON, folder, file transient property).
  • Helper/MediaManager.php (or Service/MediaManager.php depending on version) — the façade: prepareMedia, saveMedia, deleteMedia, getHandler, moveMedia.
  • Helper/*/*Handler.php — one strategy class per media type (File, Image, Video, SlideShare, Snippet). This is the real meat of the bundle.
  • Form/Type/MediaType.php + Controller/ChooserController.php — the upload/chooser UX.
  • Twig/MediaTwigExtension.php — how templates resolve media to URLs.

First use case: attach an uploaded image to an entity, persist it through the manager, and render a thumbnail in Twig.

$media = new Media();
$media->setFile($uploadedFile);                                  // transient UploadedFile
$media->setName($uploadedFile->getClientOriginalName());
$media->setContentType($uploadedFile->getMimeType());

$mediaManager->prepareMedia($media);   // handler sets location + url
$mediaManager->saveMedia($media);      // persist + flush
{# confirm exact filter names with: bin/console debug:twig | grep media #}
<img src="{{ media|media_thumb('pagepart_thumb') }}" alt="{{ media.name }}">

Implementation Patterns

1. Single media relation (the 90% case). Map a ManyToOne to Kunstmaan\MediaBundle\Entity\Media on your entity and use the bundle's form type in the admin. The form type renders the chooser modal plus a file input, so editors can pick existing media or upload new.

/**
 * @ORM\ManyToOne(targetEntity="Kunstmaan\MediaBundle\Entity\Media")
 */
protected $image;
$builder->add('image', MediaType::class, ['required' => false]);

2. Programmatic imports (CSV feeds, API sync, migration scripts). Always go through MediaManager, never $em->persist($media) directly — the handler is what computes location/url and generates image derivatives. Use prepareMedia() before persisting; it is safe to call in a loop inside a console command, but flush in batches rather than per item.

3. Galleries. Use ManyToMany with a join table plus a collection form of MediaType, 'allow_add' => true, 'by_reference' => false. Ordering, if you need it, lives in your join entity — the bundle has no ordering concept.

4. The chooser inside custom admin screens. ChooserController exposes index/chooser/bulk-upload actions; the JS opens a modal and hands back the media ID(s). If you build your own controller, follow the pattern of returning JSON with id, url, thumb and let the existing Dropzone endpoints (BulkUploadController) do uploads — don't roll your own uploader beside it, or files land outside Media.location conventions.

5. Custom handler (the main extension point). For SVG, PDF previews, S3-backed files, or a DAM sync, implement MediaHandlerInterface and register it with the manager (via the bundle's compiler pass/service tag, or $mediaManager->addHandler($handler) in old versions). Give it a type alias, then reference that alias in the kunstmaan_media.media_types config so the admin gets an icon, form type, and templates. A cloud handler typically stores the object key in location and overrides getUrl() to return a CDN URL.

6. Twig rendering. Let LiipImagine do the resizing — the image handler just resolves the original and the filter set does the rest. Keep filter sets in config.yml and reference them by name; never render media.url for large images in listings.

7. Laravel port (if that's your actual goal). The bundle's design maps cleanly:

Kunstmaan Laravel equivalent
Media entity + metadata JSON Eloquent model with $casts = ['metadata' => 'array']
MediaManager façade Singleton service / MediaService
Handler-per-type strategy Strategy classes resolved by MIME (container bindings or a MediaHandlerRegistry)
Gedmo nested-set Folder kalnoy/nestedset or plain parent_id
LiipImagine filter sets intervention/image + named presets
Chooser modal + Dropzone Livewire/Blade component
Whole bundle spatie/laravel-medialibrary gets you 80% there

If your day job is Laravel, the honest leverage is: copy the handler abstraction and media_types config idea, not the code.

Gotchas and Tips

  • No Laravel bridge whatsoever. No provider, no facade, no Blade directives. Doctrine annotations, Symfony DI, YAML config, and getRequest()-style controllers make it non-portable to Symfony 5+ too. Treat the 2014 tag as frozen.
  • Aviary is dead. Adobe acquired Aviary in 2014 and shut down the Creative SDK; aviary_api_key and the "advanced image editing" selling point are non-functional. If you need crop/rotate, use LiipImagine runtime filters or a JS cropper. Budget for removing the Aviary button from the admin templates so editors don't click into a broken iframe.
  • Handler-not-found errors. MediaManager::getHandler() resolves by contentType. Uploads producing image/svg+xml, application/pdf, or an empty MIME (common with UploadedFile::getMimeType() on some servers) blow up or fall back to the file handler. Set contentType explicitly from a trusted mapping when importing, and register handlers for every type you accept.
  • Orphan files are normal. Deleting a Media row does not reliably delete the physical file — it depends on the handler's removeMedia() implementation. Run the bundle's maintenance commands periodically (bin/console list kunstmaan_media for the cleanup/thumbnail-regeneration names in your version) and monitor the upload directory size.
  • LiipImagine misconfiguration is the #1 runtime error. A filter set referenced in Twig but absent from liip_imagine.filter_sets throws at render time. After adding filters, clear the cache and regenerate thumbnails; check write permissions on the cache directory (web/media/cache in old setups).
  • Folder tree needs Gedmo. Entity/Folder.php relies on the Gedmo tree extension (nested set). Without the listener registered, folder moves silently corrupt treeLeft/treeRight and the chooser shows a broken tree. Verify the annotations in Entity/Folder.php against your stof_doctrine_extensions setup.
  • Routes are not secured by the bundle. The chooser, bulk upload, and delete endpoints are plain controllers. Put them behind your firewall (ROLE_ADMIN at minimum) and add your own MIME/size validation — the config's allowed-type list is not exhaustive and Dropzone posts straight to the controller.
  • Asset/cache quirks. The admin UI ships its own jQuery/Bootstrap/Dropzone versions; conflicts with a newer admin theme cause the chooser modal to silently fail. After any bundle upgrade: assets:install, cache:clear, and hard-refresh.
  • Debugging recipe: config:dump-reference kunstmaan_media for real config keys → debug:container | grep kunstmaan_media to confirm the manager and handler tags are wired → inspect the media row's contentType, location, url after a failed upload, since 90% of "it doesn't show" bugs are a wrong location or a url pointing at a non-web-accessible path.
  • Extension points worth knowing: custom MediaHandlerInterface, custom form types per media type, and the media_types config map. Everything else in the bundle is UI you'll likely replace.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core