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 Nova Media Field Laravel Package

ferdiunal/laravel-nova-media-field

A Laravel Nova media field for uploading, previewing, and managing images and files directly within your resources. Adds a media picker to Nova forms, streamlining media attachment and file handling in the admin panel without custom frontend work.

View on GitHub
Deep Wiki
Context7

Getting Started

Before touching the field, make sure the substrate is in place — the field is a thin Nova UI over Spatie’s package, not a replacement for it.

  1. Install prerequisites
    composer require spatie/laravel-medialibrary
    php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="medialibrary-migrations"
    php artisan migrate
    
  2. Install the field
    composer require ferdiunal/laravel-nova-media-field
    
    Then publish assets if the package ships them:
    php artisan vendor:publish --tag=laravel-nova-media-field-assets
    php artisan nova:publish
    
  3. Make the model media-aware
    use Spatie\MediaLibrary\HasMedia;
    use Spatie\MediaLibrary\InteractsWithMedia;
    
    class Post extends Model implements HasMedia
    {
        use InteractsWithMedia;
    
        public function registerMediaCollections(): void
        {
            $this->addMediaCollection('cover')->singleFile();
            $this->addMediaCollection('gallery');
        }
    }
    
  4. Add the field to the Nova resource
    use Ferdiunal\LaravelNovaMediaField\MediaField;
    
    public function fields(Request $request)
    {
        return [
            MediaField::make('Cover', 'cover')
                ->collection('cover')
                ->singleFile(),
    
            MediaField::make('Gallery', 'gallery')
                ->collection('gallery')
                ->multiple(),
        ];
    }
    

Where to look first: open vendor/ferdiunal/laravel-nova-media-field/README.md and, more importantly, src/ — with 12 stars and a single 2024-09 release, the source is the documentation. Skim the field’s src/MediaField.php for the actual builder methods before assuming an API; the collection/preview method names are the first thing to confirm.

First real use case: a single cover image on a resource. Get that working end to end (upload in Nova → row appears in media table → URL renders on the frontend) before attempting multiple collections or conversions.

Implementation Patterns

Single vs. multiple collections. Mirror Spatie semantics in the field: call ->singleFile() in registerMediaCollections() and ->multiple() on the Nova field for galleries. Mismatched cardinality is the most common cause of “upload succeeds but field shows nothing” — Spatie silently keeps only the newest file for a singleFile() collection while the UI expects a list.

Preview via conversions, not originals. Register a small conversion in the model and point the field’s preview at it:

$this->addMediaConversion('thumb')->width(300)->height(300)->nonQueued();

Queued conversions produce broken thumbnails in Nova until the queue worker runs — use nonQueued() for thumbnails, keep heavy conversions queued.

Validation belongs in rules(), not Spatie settings.

MediaField::make('Gallery', 'gallery')
    ->collection('gallery')
    ->multiple()
    ->rules('array', 'max:5')
    ->rules(['gallery.*' => 'image|max:5120']);

Spatie’s acceptsMimeTypes is a storage constraint, not a user-facing validation error; the two should agree, but the Nova rules() array is what actually rejects the upload.

Read side stays pure Spatie. Don’t reach for package helpers in your app code:

$url    = $post->getFirstMediaUrl('cover', 'thumb');
$all    = $post->getMedia('gallery');
$srcset = $post->getFirstMedia('cover')?->getSrcset('thumb');

This keeps you portable if the field is ever swapped out — the media library is the durable layer.

Conditional display. Standard Nova field modifiers work: ->onlyOnDetail(), ->readonly(), ->hideWhenCreating(). Use ->readonly() in combination with the field for admin-only management of media that editors shouldn’t overwrite.

Disk and directory control. Set the disk in the model’s collection config ($this->addMediaCollection('gallery')->useDisk('s3')), not on the field. Mixing the two produces uploads that write to the field’s disk but generate URLs against the collection’s disk.

Resource form layout. Media fields are tall; place them at the end of the form or in a Panel with ->columns(1) so the file grid doesn’t crush neighbouring inputs on narrow viewports.

Gotchas and Tips

  • Version pinning is mandatory. One release in late 2024 and 12 stars means no maintenance guarantee. Pin the exact version in composer.json ("ferdiunal/laravel-nova-media-field": "1.0.*") and add a test that renders the resource form so a Nova upgrade breaks CI rather than production.
  • Nova upgrades break community fields first. Nova 4 → 5 changes shipped frequently; verify the field’s composer.json require block against your Nova major before upgrading. If it caps at Nova 4, you’re frozen there.
  • Assets must be published and re-published after every update. If the field renders blank in Nova after composer update, php artisan nova:publish and npm run build (or the vendor publish tag) is the first fix, not a code change.
  • Deleting a resource deletes media only if the model opts in. Spatie removes files on model delete by default, but if you ever call deletePreservingMedia() or soft-delete, orphaned files accumulate in storage. Schedule a cleanup command.
  • HasMedia is easy to forget on related models. A field rendering on a BelongsTo-adjacent resource (e.g. editing a Profile from User) will fail silently if the underlying model doesn’t implement the interface.
  • Debugging uploads: watch the browser Network tab for the Nova field’s upload endpoint, then check storage/logs/laravel.log for Spatie exceptions (FileDoesNotExist, DiskDoesNotExist). Most failures are disk misconfiguration (FILESYSTEM_DISK vs. the collection’s useDisk()) rather than the field itself.
  • Storage links. php artisan storage:link must be run in every environment (including containers/CI) or preview URLs 404 while uploads "work" — a classic false-positive.
  • Extension points are limited but real: the field delegates to Spatie, so customize behaviour through registerMediaCollections() / registerMediaConversions() on the model and a custom MediaPathGenerator for directory layouts. Overriding the field’s Vue component is possible via field.meta but undocumented — avoid it.
  • Test in a staging Nova build before adopting. Given the maturity level, run a spike with one model, one collection, one conversion, and confirm the full upload → preview → save → delete cycle works on your Nova version before wiring it into many resources.
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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource