liverbool/media-bundle
liverbool/media-bundle is a Symfony bundle for managing media assets and uploads, offering storage integration, image processing, and flexible configuration for attaching files to application entities. It helps developers add reusable media handling to Symfony projects without building upload and fi...
First, correct the premise. Despite the "Laravel package" framing, liverbool/dos-media-bundle (published as liverbool/media-bundle) is a Symfony/Sylius bundle from 2016 — zero stars, zero dependents, last release 2016-05-24. There is no ServiceProvider, no package discovery, and its composer.json will require symfony/*, doctrine/*, and sylius/*. The description.md feature list is boilerplate and should not be used to scope work.
Step 0 — confirm stack fit before anything else:
composer show liverbool/media-bundle # requires/type, if already installed
composer require liverbool/media-bundle --dry-run # expect resolution failure
If the second command doesn't produce a working dependency graph against your PHP/Symfony constraints (the expected result on anything modern), stop. Do not use --ignore-platform-reqs to force it.
If you inherited it in a legacy Sylius app, read in this order:
composer.json — PHP/Symfony/Sylius constraints and transitive pins.DependencyInjection/Configuration.php — the authoritative config tree (the README, if any, is not).Model/ and Resources/config/doctrine/ — interfaces to implement and mapped superclasses to extend.Uploader/ (or equivalent), EventListener/, Form/Type/ — the actual upload flow.Resources/config/routing.* — only relevant if you use the built-in upload/download controllers.The day-to-day Laravel answer: don't use this package — use spatie/laravel-medialibrary (polymorphic attachment, collections, conversions, multi-disk) on top of Storage/Flysystem. First use case to learn that stack: attach an image to a model and generate a thumbnail.
composer require spatie/laravel-medialibrary
php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag=migrations
php artisan migrate
class Product extends Model implements HasMedia
{
use InteractsWithMedia;
public function registerMediaCollections(): void
{
$this->addMediaCollection('images')->useDisk('s3');
}
public function registerMediaConversions(?Media $media = null): void
{
$this->addMediaConversion('thumb')->width(300)->queued();
}
}
$product->addMediaFromRequest('image')->toMediaCollection('images');
$product->getFirstMediaUrl('images', 'thumb');
That exercises the whole flow — model relation, disk config, derivative generation, URL rendering — and is the fastest way to see what this bundle would have done if it were maintained.
Concept mapping (for porting or reading the bundle as prior art):
| Bundle concept | Laravel equivalent |
|---|---|
Media Doctrine entity, OneToOne/OneToMany |
media table + HasMedia polymorphic relation |
upload_dir / upload_path config |
filesystems.disks.* + Storage::disk() |
| Uploader service writing to web root | addMediaFromRequest()->toMediaCollection() |
| Path helper in Twig | getFirstMediaUrl() / Storage::url() |
| Form type + upload listener | Form request validation + addMediaFromRequest() |
Pattern A — replace, don't wrap (recommended). The bundle's capabilities are superseded on both stacks. On Laravel, reach for:
Workflow:
media table with polymorphic model_type/model_id, uuid, collection_name, disk, file_name, mime_type, size, generated_conversions.HasMedia; register collections and conversions per model.mimes, max, image dimensions) before the model touches the disk.temporaryUrl(), not a public /media path.Pattern B — contain a legacy Sylius install, then retire it. When the bundle is already in production:
composer.lock committed and --prefer-dist disabled.store, retrieve, delete, url) at every call site so the bundle becomes swappable.Storage (Laravel side).composer.json before the next framework upgrade, not during it.Laravel-side integration tips:
ON DELETE CASCADE or a deleted model observer, plus $model->clearMediaCollection() on purge, to avoid orphaned files.uuid/hash prefix) — never trust the client filename.disk per collection.Storage::fake() in tests and assert both rows and disk contents:Storage::fake('images');
$product->addMediaFromString('x')->usingFileName('a.jpg')->toMediaCollection('images');
Storage::disk('images')->assertExists(...);
$this->assertDatabaseHas('media', ['model_id' => $product->id]);
Reference-only use. If you're designing an in-house media module, skim the bundle's Model/ layout (interface vs mapped superclass separation) in one sitting — then build against maintained libraries. Do not vendor it as a runtime dependency.
description.md. The feature list ("Laravel-friendly configuration", polymorphic Eloquent relations) is generated boilerplate. Verify claims against composer.json and source, every time.dos-media-bundle, published as media-bundle, vendored under liverbool. Don't infer bundle class names from the package name — grep -r "class .*Bundle" vendor/liverbool/media-bundle/src/ before touching the kernel.vendor/ — or, worse, be autoloaded and register nothing, giving you false confidence. Confirm with composer show before assuming it can do anything.upload_dir (filesystem root) vs upload_path (web path) must stay consistent, and %kernel.root_dir% vs %kernel.project_dir% differ across Symfony versions. In Laravel terms: treat the equivalent of "path on disk" and "public URL prefix" as separate, explicit config values.Media class you extend; getting Doctrine inheritance and the schema right when porting to a migration is a common source of silent column drift. Diff the generated schema against the new one before backfill.photo.jpg uploads overwrite each other. Assume collisions and generate unique names unconditionally.bin/console debug:container | grep -i media, debug:router, lint:yaml config, and clear the cache after any config change — many DI errors surface only at cache warmup.php artisan about, php artisan route:list, Storage::disk('x')->exists($path) as a ground-truth check, Event::fake() to isolate upload listeners, and Model::preventLazyLoading() to catch N+1s on media relations.--ignore-platform-reqs on a decade-old dependency produces compile-time container errors and Doctrine incompatibilities that aren't worth the debugging debt. Verify with --dry-run and walk away on failure.How can I help you explore Laravel packages today?