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

johnkrovitch/media-bundle

A PHP media bundle from johnkrovitch for managing and serving media files in web applications. It aims to simplify uploads, storage, and asset handling, but with minimal adoption and sparse documentation it is best suited to experimentation rather than production use.

View on GitHub
Deep Wiki
Context7

Getting Started

Before anything else: this is not a Laravel package. johnkrovitch/media-bundle is a Symfony bundle ("Media Bundle for Cms"), published as a Composer package but wired for Symfony's kernel, DI container, and Doctrine. In a Laravel app you can composer require it, but nothing will register itself — no service provider, no config publish, no facade. Treat it as reference source code, not a dependency.

If you are actually on Symfony, the minimal path is:

  1. composer require johnkrovitch/media-bundle and check composer.json in the package for its symfony/* and php constraints against your app — a 2020-vintage bundle will likely cap out at Symfony 4/5 and PHP 7.x.
  2. Register the bundle class in config/bundles.php (find the namespace root in the package's src/ — the class name is the bundle's *Bundle.php file).
  3. Look in src/DependencyInjection/ for the extension alias (this is the config key you'll use under config/packages/*.yaml) and Configuration.php for the exact tree of options. Do not guess option names — this package has no meaningful docs, so Configuration.php is the real documentation.
  4. Check src/Resources/config/ for services.yaml, routing, and Doctrine mappings. Note whether mappings are XML/YAML/annotations — if annotations, they'll break on PHP 8 / newer Doctrine.
  5. Run bin/console doctrine:schema:update --dump-sql first to see what tables it wants before committing a migration.

First use case for a CMS: a shared media library — upload an asset, persist metadata, generate derivatives (thumbnails), and reference the media entity from content entities via a relation rather than storing raw paths.

If you are on Laravel — which is the likely situation — do this instead:

Bundle capability Laravel equivalent
Media entity + Doctrine mapping Eloquent model with morphTo
Filesystem abstraction Storage facade + config/filesystems.php disks
Image derivatives intervention/image or spatie/image
Upload handling / validation FormRequest + image/mimes rules
Twig rendering helpers Blade component + <x-media>
Admin list/edit Filament or Nova field

spatie/laravel-medialibrary already covers ~90% of what this bundle does, is actively maintained, and has thousands of dependents. Read this bundle's src/ for domain modeling ideas, then implement against Spatie. Budget half a day for that read; it is likely small.

Implementation Patterns

Symfony-side wiring (if you proceed there). The bundle almost certainly follows the classic CMS pattern: a Media-ish entity with fields for filename, original name, mime type, size, and a folder/category relation, plus a service responsible for persisting the file and writing derivatives. Expect the entity to be extended by your app entity (Doctrine inheritance or a simple ManyToOne from your content entity), because CMS bundles of this era assume you'll own the association. Override the bundle's Twig templates by placing files of the same name under templates/bundles/<BundleName>/ — this is the standard Symfony override path and the safest extension point.

The workflow to replicate in Laravel:

upload request → validate (mime, size, extension) → store original to
a non-public disk with a generated name → create Media row (uuid, name,
mime, size, disk, path, owner morph) → dispatch ProcessMedia job →
worker generates derivatives → update Media with derivative paths →
serve via signed/route URL, never a raw public path

Keep originals immutable and derivatives regenerable. Never store a derivative path without also storing the transform parameters (width, height, fit) — otherwise you can't rebuild the library when you change image processing.

Eloquent model sketch:

class Media extends Model
{
    protected $guarded = ['id'];
    protected $casts = ['meta' => 'array', 'size' => 'integer'];

    public function mediable(): MorphTo { return $this->morphTo(); }

    public function url(string $conversion = 'original'): string
    {
        return Storage::disk($this->disk)->url($this->pathFor($conversion));
    }
}

Add a HasMedia trait with morphMany(Media::class, 'mediable') and a registerMediaConversions() hook — that shape mirrors what the bundle gives you in Symfony and keeps the port honest.

Integration tips. Make the storage disk a config value, not a constructor argument, so tests can swap to Storage::fake(). Do derivative generation in a queued job so an image upload doesn't hold the request for 3 seconds. If the bundle exposes a post-persist event (look for Event/ or *Event.php in src/), that's the right seam for your own thumbnailing/virus-scan/EXIF-stripping; the Laravel port is a model observer or an event listener on MediaCreated.

Gotchas and Tips

  • Abandoned since July 2020. No commits in ~5 years, PHP 8.x compatibility unverified, and any Symfony 6/7 API it touches (especially Doctrine annotation mappings and ContainerBuilder signatures) has likely moved. Do not put this on a critical path.
  • Near-zero adoption signal. 1 star, 0 dependents means no Stack Overflow answers, no third-party tutorials, and no one else has hit your bug before you. Every issue you find is yours to fix. The 0.305 score reflects exactly this, not code quality.
  • MIT license is the saving grace. Forking and porting is legally clean. If you do fork, pin the commit and vendor it as a path repository rather than relying on the tag.
  • File upload security is on you. Whatever validation the bundle ships with, add your own: check real MIME via finfo rather than trusting the client-supplied type, reject double extensions (shell.php.jpg), generate filenames server-side, store outside the webroot, and ensure the upload directory can't execute PHP (php_flag engine off / nginx location ~ \.php$ { deny all; } inside uploads).
  • DB/disk is not transactional. A crash between Storage::put() and $media->save() leaves an orphan file; a delete that removes the row but fails on the file leaves an orphan blob. Add a scheduled reconciliation command, and prefer deleting files via a queued job after the row is gone so failures are retryable.
  • Cascade deletes are a classic miss. If the polymorphic owner is deleted, nothing removes the media. Use Model::deleting hooks or a prunable model to clean up, and test it.
  • Config quirks. In Symfony the bundle's options live under a snake_cased alias of the bundle name in config/packages/; resolve the alias from DependencyInjection/*Extension::getAlias(), not from the README. Upload-directory values are usually %kernel.project_dir%-relative parameters — a common failure is a path that resolves correctly in dev but not in a container where the project dir is read-only.
  • Debugging. On Symfony: bin/console debug:container | grep -i media to confirm services registered, and the profiler's Doctrine panel to see the queries. On a Laravel port: Storage::fake() in tests catches path bugs early, and php artisan about won't help — check config/filesystems.php and the storage:link symlink first when URLs 404.
  • Extension points worth knowing before you fork: custom storage adapter (implement the bundle's filesystem interface if one exists), Twig template override, Doctrine event listener for post-persist work, and the DI extension for config defaults. Those four are where 90% of real customization happens.
  • Decision rule: if you're on Symfony 4/5 and need a quick media entity, read the code and possibly vendor it. If you're on Laravel, on Symfony 6+, or on PHP 8.2+, do not adopt — port the model, use Spatie, and move on.
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