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

Laravel Media Laravel Package

whitecube/laravel-media

Laravel Media offers a simple, configurable way to attach, store, and manage media files in Laravel applications, with support for uploads, conversions, and clean model associations.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and publish its assets:

composer require whitecube/laravel-media
php artisan vendor:publish --tag="media-config"
php artisan vendor:publish --tag="media-migrations"
php artisan migrate

First places to look:

  1. config/media.php — storage disk, path conventions, default variant definitions, and queue settings. This is where most day-to-day tuning happens.
  2. The HasMedia (or equivalent) trait shipped with the package — this is the entry point you add to any Eloquent model that owns media.
  3. The migrations — check the media table schema before you decide whether to keep the package's table or relate media through your own pivot.

First use case: attach a single image to a model and let the package generate its variants.

use Whitecube\Media\Concerns\HasMedia;

class Post extends Model
{
    use HasMedia;
}

$post->attachMedia($request->file('cover'), 'cover');

Then confirm on disk that the original plus the configured variants were written, and that the media record points at the right model. If variants are missing, the queue worker is the usual culprit — see Gotchas.

Implementation Patterns

Model-centric attachment. Keep media concerns on the model via the trait and expose named "collections" (cover, gallery, downloads). This keeps controllers thin and makes it obvious in the model which slots accept media.

Variant definitions belong in config (or a dedicated class), not in controllers. Define the sizes/formats once, keyed by collection, so every model using that collection gets consistent output. When a collection needs bespoke variants, override at the model level rather than branching in the controller.

Replace, don't delete-and-recreate. Replacing an existing image in place is the intended workflow — the package handles swapping the file and (as of v1.0.5) regenerating variants for replaced images. Use the replace path so relation IDs and any references to the media record stay stable.

Queue variant generation for anything user-uploaded. Synchronous generation is fine in tests and seeders, but in request cycles it will block on large images. Configure the queue connection in config/media.php and make sure your worker is running in every environment, including staging.

Regeneration as an explicit command. When you change variant definitions, treat it as a deployment step: run the package's regeneration command (or dispatch a job) rather than expecting existing files to update themselves. This pairs well with a feature flag if the change is visible to users.

Cleanup on delete. Wire media cleanup into model deletion (observer or deleting hook) so files don't orphan on the disk. The package handles the record; confirm it also removes the underlying files in your config, and add a scheduled sweep for stragglers.

Testing. Use Storage::fake() and assert on the media records plus the expected variant filenames. Because generation may be queued, either set the queue to sync in the test environment or Queue::fake() and assert the job was dispatched.

Gotchas and Tips

Upgrade to v1.0.5 if you replace images. v1.0.5 fixes variant generation for new and replaced images and prevents listener pile-up with needless regeneration. On ≤1.0.4, repeated image updates could leave stale or missing variants and trigger redundant work. This is a bug fix, not a breaking change — upgrading is low risk, but re-verify variant output for any model that replaces images frequently.

Listener pile-up is a symptom worth understanding. The v1.0.5 fix implies model/event listeners were being registered more than once in some flows. If you register your own media observers or listeners alongside the package, guard against double-registration (e.g. registering in a service provider's boot exactly once, not per-request or in a loop). Duplicate listeners show up as variants generated twice or jobs dispatched twice — check your queue logs for repeated identical jobs before assuming it's a package bug.

"Needless regeneration" wastes queue throughput. Regeneration is expensive; avoid triggering it on every save. Only touch media when the media itself changes, not when unrelated attributes on the model are updated. If you see variant jobs firing on plain $model->save() calls, that's the pattern to fix.

Disk and path config is global. A single misconfigured disk in config/media.php affects every model. Verify php artisan storage:link and that the configured disk's visibility matches how you serve files (public URL vs. signed temporary URL).

URL generation vs. storage path. Don't hand-build asset URLs from the stored path. Use the package's URL helper so disk visibility, CDN prefixes, and path conventions stay consistent — especially after a config change.

Ordering matters on replace. If your own code reads the media record immediately after a replace, be aware variant generation may still be queued. Make downstream consumers tolerant of variants not existing yet, or force synchronous generation for that path.

Extension points. Config-driven variants and the model trait are the safe customization surfaces. Subclassing package internals is possible but will make future patch releases (like this one) harder to adopt — prefer config and observers over overriding classes.

Debugging checklist for missing variants: (1) is the queue worker running, (2) does the disk in config match the disk the file actually landed on, (3) are variants defined for that collection name, (4) is the model actually using the trait, (5) on ≤1.0.4, were listeners double-registered.

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.
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
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console