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

Ux Filemanager Laravel Package

mezcalito/ux-filemanager

A Laravel package that adds a ready-to-use file manager UI for browsing, uploading, renaming, and deleting files and folders on your configured storage disks. Ideal for admin panels, it offers a simple, customizable way to manage files without building CRUD screens.

View on GitHub
Deep Wiki
Context7

Getting Started

mezcalito/ux-filemanager is a Symfony bundle (Symfony UX + Stimulus), not a Laravel package — if you're coming from Laravel, expect to drop the familiar Storage/File facade mental model and think in terms of Flysystem filesystems + a Symfony form type + a Stimulus-driven picker UI. There is no Laravel integration; you can only use it in a Symfony app (or port the front-end pieces).

As of 0.1.7 the package supports Symfony 8 / PHP 8.5 alongside the older Symfony lines — still Symfony-only, but actively maintained against the newest framework release.

Minimal setup path:

  1. Install

    composer require mezcalito/ux-filemanager
    

    Flex should register Mezcalito\UxFileManager\MezcalitoUxFileManagerBundle and import its routes. If not, add the bundle manually and import the routing file from the bundle (@MezcalitoUxFileManager/config/routes.yaml or similar — confirm with php bin/console debug:router | grep -i file).

  2. Wire up the front-end assets. The bundle ships a Stimulus controller and CSS. In an AssetMapper app, confirm the controller is discoverable/imported in assets/controllers.json or importmap.php; in an Encore app, run your asset build. Without this the modal/picker will render but do nothing.

  3. Configure at least one filesystem. The bundle does not ship a storage backend — it delegates to Flysystem (typically via league/flysystem-bundle). Declare a filesystem in your Flysystem config, then point the file manager at it:

    # config/packages/flysystem.yaml (illustrative — verify key names)
    flysystem:
        storages:
            default.storage:
                adapter: 'local'
                options:
                    directory: '%kernel.project_dir%/var/storage/default'
    
    # config/packages/mezcalito_ux_filemanager.yaml
    mezcalito_ux_filemanager:
        filesystems:
            default:
                storage: 'default.storage'
    

    Always confirm the real schema with:

    php bin/console config:dump-reference mezcalito_ux_filemanager
    
  4. Smoke-test the manager route. Hit the file-manager route (usually /file-manager or similar; verify in debug:router) and try uploading a file through the UI. This proves assets, routing, filesystem config, and write permissions all line up before you touch forms.

Where to look first: config:dump-reference mezcalito_ux_filemanager for the real config tree, debug:router for the manager endpoints, the bundle's Form/FileManagerType.php for form integration, and the assets/ directory for the Stimulus controller (selection events live there).

First real use case: attach an image/document to a Doctrine entity. Add a FileManagerType field to your form, let the user pick or upload via the modal, persist the returned storage path as a string column, and render it later via asset() or a Flysystem URL resolver.

Implementation Patterns

Form-integrated picker (the 80% case). Use the bundle's form type instead of a raw <input type="file">. It returns a path string relative to the configured filesystem root:

$builder->add('imagePath', FileManagerType::class, [
    'filesystem' => 'default',
    'label'      => 'Image',
]);

Persist that string directly (private ?string $imagePath). Do not store absolute paths or URLs — you want to stay storage-agnostic so you can move to S3/CDN later without a data migration.

Multiple filesystems for public vs. private. Declare e.g. public (web-accessible, local adapter under public/uploads) and private (under var/storage). Pass 'filesystem' => 'private' on sensitive fields. This is the cleanest way to keep PII docs out of the public web root.

Standalone manager page + custom controller. The bundle exposes the browsing UI, but you still own serving files. Typical pattern: a controller action that takes an id/path, validates access with your normal security voters, then stream-downloads via the Flysystem filesystem:

return $this->file($filesystem->readStream($path), basename($path));

This keeps authz in your app instead of relying on the bundle's UI.

Rendering after selection. For private files, expose a signed/authorized route. For public ones, use Flysystem's public URL ($filesystem->publicUrl($path)) or asset('uploads/' . $path). Pair with LiipImagine (or a Flysystem thumbnailer) for responsive image variants — the bundle is a manager, not an image pipeline.

Wiring the picker into non-form UI. Use the Stimulus controller directly when you build custom admin tooling (e.g., a repeater of gallery items). Attach the controller to a container, listen for the selection event emitted by the bundle's controller, and hydrate hidden inputs. Read the controller source to confirm the event name/payload — it's the extension point most day-to-day customization hangs on.

Uploads and replacements. Let the manager own uploads into the configured filesystem; your app only stores references. On entity delete, either null out the column or add an onFlush/event listener that calls $filesystem->delete($path) — there's no automatic GC in the bundle, so orphan cleanup is your job.

Security integration. Wrap the manager routes in your firewall via access_control:

security:
    access_control:
        - { path: ^/file-manager, roles: ROLE_ADMIN }

Treat the manager as an admin back office, not a user-facing feature, unless you've audited its authorization model for multi-tenant use.

Gotchas and Tips

  • It's Symfony, not Laravel. No Storage::disk(), no Blade component, no package:discover. If your team is Laravel-first, budget for the framework mismatch before adopting — the value is the ready-made UX picker, not the storage abstraction (Flysystem does that part).
  • The manager route ships unauthenticated by default. This is the #1 deployment risk: it can browse/upload to the configured filesystem. Add access_control and, if multi-tenant, scope per-user filesystems in a custom controller rather than exposing the shared manager.
  • Asset pipeline is the most common "nothing happens" failure. If the UI renders but the modal never opens or selection doesn't populate the field, it's almost always a missing Stimulus controller registration / unbuilt asset. Check assets/controllers.json (AssetMapper) or your Encore build output, and look at the browser console for 404s on the controller JS. Newer Symfony UX versions tighten controller/importmap resolution, so re-verify after upgrading Symfony itself.
  • Config key drift. The README may lag behind the released config tree. Always trust config:dump-reference over blog posts or the README.
  • Filesystem adapter errors surface late. A missing storage: reference or a nonexistent directory: produces errors only when the UI tries to read/write. Validate by uploading immediately after setup, and make sure the var/ (or public/uploads/) directory is writable by the PHP user.
  • Paths are filesystem-relative. Don't prepend / and don't assume they're URLs. Normalize ltrim($path, '/') before passing to Flysystem to avoid adapter-specific quirks between local and S3.
  • No built-in thumbnails, MIME validation, or filename deduplication. Enforce allowed extensions/sizes at the form/controller level (File constraint won't apply here — you're storing a path string, so add a custom validator that re-checks the resolved file's MIME/size). Add collision handling if users upload same-named files into one directory.
  • Watch PHP upload_max_filesize / post_max_size. The bundle can't bypass PHP limits; large uploads silently fail when these are set low.
  • Deletion is manual. Deleting the entity does not delete the file. Add a Doctrine listener or domain service for cleanup, or accept orphaned files and run a periodic sweep.
  • Version compatibility is now broader, not narrower. 0.1.7 added Symfony 8 / PHP 8.5 support — there are no deprecations or config changes called out in the changelog, so upgrading from 0.1.6 should be a plain composer update. Still pin the version in composer.json and eyeball the diff between releases before bumping.
  • Low adoption risk. 22 stars and 0 dependents means few eyes on edge cases. Read the bundle's source for the pieces you depend on (form type, Stimulus controller, routes), and consider wrapping it behind your own thin service so a future drop-in replacement is a one-file change.
  • Debugging checklist: debug:router (routes exist?), debug:config mezcalito_ux_filemanager (config parsed?), browser console (assets loaded?), var/log/dev.log (Flysystem errors?), and a direct $filesystem->write() in bin/console (storage writable?). Work that order — it isolates routing → assets → config → storage in four steps.
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