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

Elfinder Laravel Package

components/elfinder

A Laravel component for integrating elFinder, the open-source file manager. Add file browsing, uploads, folder management, and editor support to your app with configurable roots, connectors, and Blade-friendly rendering, simplifying elFinder setup in Laravel views.

View on GitHub
Deep Wiki
Context7

Getting Started

This is the Laravel binding for elFinder — it ships a service provider, an Elfinder facade, a controller, a published config, and Blade views, so the browser UI and the PHP connector are wired together for you. Treat it as a connector-plus-UI, not a storage abstraction.

1. Install

composer require helios-ag/elfinder-component

On Laravel 5.5+ the Helios\Elfinder\ElfinderServiceProvider and the Elfinder facade are auto-discovered. On older apps, add them to config/app.php.

2. Publish config and assets

php artisan vendor:publish --provider="Helios\Elfinder\ElfinderServiceProvider"

Publish both the config (config/elfinder.php) and the assets (which land in public/vendor/elfinder). If you publish selectively, use the tags listed by php artisan vendor:publish --provider=... with no tag — the asset copy is the one people miss, and the UI will render a blank page without it.

3. Configure one root The first thing to read is the published config/elfinder.php — it documents the wrapper's own keys (route.prefix, route.middleware, dir, and often a roots/disks block) on top of the raw elFinder connector options. Set at minimum:

'dir' => [
    'path' => base_path('files'),   // must exist and be writable
    'URL'  => '/files/',            // public URL serving the same directory
],

4. First use case: a standalone file manager Visit /elfinder (the route prefix comes from the config). That's the whole first-use scenario — a web-based file manager over a local directory. From there, the natural second step is embedding it in an admin panel and wiring it into a WYSIWYG editor.

Before going further, confirm the php artisan route:list | grep elfinder output shows elfinder.show, elfinder.connector, and the editor helper routes, and that public/vendor/elfinder exists. Those two checks solve most "it doesn't work" reports.

Implementation Patterns

Embedding in an admin page. Don't try to inline the elFinder UI inside a heavy dashboard layout — the file manager expects the full window and its own JS. Wrap it:

<iframe src="{{ route('elfinder.show', 'my-folder') }}"
        style="width:100%;height:75vh;border:0"></iframe>

Alternatively include the published elfinder::elfinder view directly on a bare Blade page (no @extends) so you don't fight the layout CSS.

WYSIWYG / editor integration is the strongest day-to-day use case. The package registers purpose-built entry points so the editor's "Browse" button can open a popup and return a URL:

  • CKEditor: set filebrowserBrowseUrl / filebrowserImageBrowseUrl to route('elfinder.ckeditor').
  • TinyMCE (v4): use route('elfinder.tinymce4'); older route('elfinder.tinymce') for v3.
  • Generic popup callback: route('elfinder.popup').

The popup routes exist so you don't have to write your own "pick a file, return its URL" glue — that's the reason to use this package over calling the connector directly.

Locking it down per-user. Two layers:

  1. Route middleware — the wrapper reads route.middleware from the config; set it to ['web', 'auth'] (or your admin gate). Never ship the default web-only config to production.
  2. Per-path accessControl inside the root options — elFinder calls this for every operation:
'accessControl' => function ($attr, $path, $data, $volume) {
    if (! auth()->check()) return false;
    // allow read for everyone logged in, write only for admins
    $write = in_array($attr, ['write', 'rm', 'mkdir', 'mkfile', 'upload', 'paste', 'duplicate', 'rename', 'archive', 'extract'], true);
    return $write ? auth()->user()->isAdmin() : true;
},

This is where most real customization happens — quotas, per-tenant folders, read-only archives.

Multiple roots / per-tenant directories. Define several roots in the config (or the wrapper's roots equivalent) each with its own path + URL, and give each an accessControl that checks the current user/tenant. This is the standard multi-tenant media library pattern: one root per tenant directory, an accessControl closure that compares $path against the user's tenant folder.

Mounting a Laravel disk. If the config exposes a disks/Flysystem block, you can point a root at an Storage disk path and generate the URL with Storage::url(...) (or Storage::disk('public')->url(...)). This is how you avoid hand-writing absolute paths and keep php artisan storage:link as the single source of truth for public URLs.

Programmatic / headless use. The facade gives you the connector instance, which is useful for maintenance tasks rather than UI work — e.g. iterating volumes to build a cache warmer, or validating that every configured root path exists before rendering the page:

foreach (config('elfinder.roots', [ config('elfinder.dir') ]) as $root) {
    // check is_dir / is_writable and log warnings
}

Most teams only ever use the browser routes; the facade is a troubleshooting and ops tool.

Gotchas and Tips

Maintenance status is the biggest risk. The last release is July 2020 and there are zero dependents on record. That release predates Flysystem 2/3 and Laravel 9's storage changes, so on Laravel 9+ expect composer to resolve an old league/flysystem and/or runtime fatals in the connector. Practical options: pin the app to Laravel 8 / PHP 7.4–8.0, fork just the connector glue against current Flysystem, or embed studio-42/elfinder directly with a small custom connector. Decide this before you build features on top of it.

CSRF on the connector. Uploads and many mutating operations POST to elfinder/connector. If your app runs the route inside the web group, you either need elFinder to send the token or you must add the connector URI to VerifyCsrfToken::$except. Verify this early — a 419 on upload is the classic first symptom, and it looks like a permissions bug.

Missing assets. The routes work without published assets, so you get a 200 with a broken UI. Always confirm public/vendor/elfinder is populated; in CI, make the publish step part of deploy.

Config caching breaks closures. An accessControl closure inside config/elfinder.php cannot be var_exported by php artisan config:cache — it fails or silently degrades. Register closures at runtime in a service provider (or bind them after config load) if you use config caching in production.

Path vs URL must agree. The root path is where PHP reads/writes; URL is how the browser fetches it. Mismatch shows up as broken thumbnails, a working upload but 404 previews, or downloads that point at the wrong host. Keep URL relative to APP_URL and make sure the web server actually serves that directory (symlink it if it lives under storage/).

Permissions and thumbnails. The root must be writable by the PHP user, and elFinder writes its own .tmb thumbnail directory inside the root by default. In containerized/read-only-mount setups, set an explicit writable tmbPath. Locked-down deployments also need upload write access for chunked uploads to assemble temp parts.

PHP extensions. The connector needs mbstring, gd (thumbnails), zip (archive create/extract), fileinfo, and exif for image metadata. Missing zip is the usual cause of "archive button does nothing" with no obvious error.

Check the network tab, not the log. The connector returns JSON errors with HTTP 200, so Laravel's log stays quiet. Debug by inspecting the elfinder/connector response body and, if needed, flipping elFinder's debug option on the connector to get a stack trace in the response. Server-side 500s from the connector are almost always path, permission, or Flysystem-version issues.

Route and asset prefix collisions. If you already own elfinder, files, or a vendor/ asset path, change route.prefix in the config rather than renaming your routes; the popup/editor helper URLs are generated from it, so a mismatch silently breaks the editor "Browse" button.

Upload limits. elFinder's chunking only helps if upload_max_filesize and post_max_size are large enough for one chunk; with default 1-chunk behavior they behave like plain limits. Raise both, and make sure max_execution_time covers large uploads and archive extraction.

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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core