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 Asset Manager Laravel Package

innopanda/laravel-asset-manager

A Livewire and Spatie Media Library asset manager for Laravel with a virtual folder tree, reusable picker modal, thumbnails, multi-select, file replacement, version history, and optional Filament form integration.

View on GitHub
Deep Wiki
Context7

Getting Started

Install / upgrade

composer require innopanda/laravel-asset-manager
# or, for existing installs
composer update innopanda/laravel-asset-manager

Then, on a fresh install: publish the package's config/migrations/assets if the README calls for it (php artisan vendor:publish), run php artisan migrate, and clear caches (php artisan optimize:clear) after upgrading to v1.0.9 so the updated JS/CSS assets and Livewire component definitions are picked up.

Where to look first

  1. The Filament AssetPicker field class — this is the public API you'll use in resource forms.
  2. The Livewire MediaBrowser component — this is where selection state lives and where the picker hands off.
  3. The package config file — storage disk, allowed mime types, and any JS asset registration.

First use case

Add a single-image field to an existing Filament resource, verify upload + selection end-to-end, then flip the same field to multiple selection for a gallery-style field. That two-step path exercises the whole flow (picker → browser → confirm → hydration) with minimal surface area, and it's the exact path v1.0.9 changed, so it doubles as your upgrade smoke test.

Implementation Patterns

Single asset (the baseline)

Use AssetPicker as a form field in a Filament resource, backed by a nullable column. Persist the asset ID, not the URL:

AssetPicker::make('featured_image_id')
    ->label('Featured Image'),

Multiple assets

v1.0.9 makes the multi path first-class: persistent selection state, toggling, visual indication, and a payload of selected assets with IDs and URLs. Use it for galleries, repeaters of media, or "downloads" sections.

AssetPicker::make('gallery_ids')
    ->multiple() // confirm exact method name against the field class
    ->label('Gallery'),

Store the result in a JSON column ($casts = ['gallery_ids' => 'array']) or, for a normalized model, sync() the returned IDs into a pivot table.

Persist IDs, resolve URLs on render

The picker returns assets with both IDs and URLs — a convenience for client-side previews, not a storage format. Keep IDs in the database and resolve URLs at render time via your media model/disk. This survives disk changes, CDN migrations, and signed/temporary URL expiry.

Non-Filament Livewire usage

The MediaBrowser is a Livewire component, so you can mount it from any Livewire screen, not just Filament. The flow is: your component renders the picker trigger → the trigger dispatches an init/open event carrying the current selection → the browser manages the multi-select state → the browser dispatches a confirmation event with the chosen payload → your component listens with #[On('...')], updates its own public property, and closes the modal. Read the package's event names from the source rather than guessing; treat them as semi-public API.

Form hydration for edit screens

On edit, the picker must be seeded with existing selections before the browser opens. Hydrate from the model's stored IDs in the field's afterStateHydrated() / formatStateUsing() hook so the browser opens showing the current gallery checked — this is the most common "why is my gallery empty on edit" bug.

Testing

Livewire::test() the MediaBrowser directly: set the selection property, call the toggle method, assert the selection array matches, and assertDispatched() the confirmation event. For the Filament field, the cheapest reliable coverage is a feature test that saves a form with two assets and asserts both IDs land in the JSON column.

Logging while integrating

v1.0.9 adds detailed logging across the AssetPicker → MediaBrowser selection flow. Wire it up once while building out a new integration (tail the log during a click-through) and then dial the channel down for production — see Gotchas.

Gotchas and Tips

  • URLs in the payload are ephemeral. Temporary/signed URLs expire. Never store them; store IDs and re-resolve. If you cache rendered output, key it on the asset ID and the disk config.
  • Multiple-picker collisions on one page. Selection events are Livewire dispatches, and Livewire listeners are global by default. If a form has two AssetPickers, scope the listener to a field identifier (or use #[On] with a unique event name per field instance) or the second browser will inherit the first's state.
  • State lives in the component, not the model. Modal close/reopen, full page reloads, or a Livewire re-render that remounts the browser can drop the multi-selection. Re-seed from the model's stored IDs on every mount rather than assuming the browser remembered.
  • Don't rely on selection order. "Toggle before confirm" implies a set, not a sequence. If the gallery is ordered, sort explicitly on your side and persist an explicit ordering column.
  • Version pinning. AssetPicker sits on top of Filament's form and Livewire; a Filament major upgrade can break the field before this package catches up. Pin innopanda/laravel-asset-manager in composer.json and test upgrades together.
  • Logging verbosity is a prod concern. The new detailed selection logging is genuinely useful while debugging a broken picker, but treat it as a switch to turn off — otherwise a media-heavy admin panel writes a lot of noise.
  • Republish assets after upgrade. If your install publishes the package's JS/CSS, composer update alone won't refresh the served files. Check public/vendor/... (or your Vite build) and re-publish.
  • Storage disk mismatch. The disk the picker uploads to and the disk you call Storage::disk(...)->url() on at render time must be the same, otherwise you'll get valid IDs with broken images. Centralize the disk in config and read it in one place.
  • Backward compatibility is the good news. v1.0.9 explicitly preserves single-asset selection behavior, so the upgrade risk is contained to the multi path. Run your gallery feature test after upgrading, and specifically exercise: open on edit, deselect one item, reselect it, confirm.
  • Upgrade smoke test, in order: clear caches → republish assets → open an edit form with 2+ existing assets → toggle one off → confirm → save → reload. If the saved JSON matches expectation, the new selection-state handling is wired correctly.
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.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo