Open-source project
barryvdh/laravel-elfinder avatar
barryvdh/laravel-elfinder

laravel-elfinder, a file manager wired into Laravel's filesystem disks

elFinder bundle for Laravel

757 stars169 forksPHPLicense varies

At a glance

What is it?
barryvdh/laravel-elfinder brings the elFinder web file manager into a Laravel application, with the assets published by an artisan command, the routes registered by a service provider, and the filesystem disks mounted as roots so the manager browses S3 or any Flysystem adapter rather than a local folder.
Who is it for?
Adopt laravel-elfinder if your Laravel application needs a browsable file picker or a small file manager and you want the browsable roots to be Laravel disks rather than raw folders. Skip it if you need multi-tenant isolation with per-user credentials, since the connection model is a single configured session.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 56 days ago.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the package actually is

This package integrates elFinder by Studio-42 into Laravel, making the PHP files available through Composer with autoloading and the assets available through a publish command. It also provides example views for standalone use, TinyMCE and CKEditor.

The important detail is how the elFinder code gets there. The files are not vendored into this repository. They are updated from a separate build repository, barryvdh/elfinder-builds, and the composer.json brings in the studio-42/elfinder package. That is why the AssetHelper in the views looks at the installed versions of studio-42/elfinder and this package together, and why the README tells you to publish the assets after every update.

There is a version warning at the very top. For Laravel 8.x and older, use the latest 0.4 version. The current line is 0.6, and the release history shows v0.5.4 in February 2025, v0.5.5 in March 2026 and v0.6.0 in April 2026, with the last push on 2026-08-30. So the current release targets modern Laravel and the older one is explicitly parked.

The licence field on the repository reports it as not classifiable by GitHub, while the Packagist badge in the README links to the MIT licence chooser page. The composer.json and the repository's readme.md are the places to confirm the terms for your own use.

The repository layout is a standard Laravel package: src/ for the PHP code, config/ for the configuration file, resources/ for the views, tests/ for the test suite with a phpunit.xml.dist, and a changelog.md.

Installing it and the publish step that people forget

Installation is a Composer require:

bash
composer require barryvdh/laravel-elfinder

Then the assets have to be copied to the public folder:

bash
php artisan elfinder:publish

The README is emphatic about that second step, including a note to use the elfinder:publish command rather than the old publish command for future changes, and to publish the assets after each update, or to add the command to the post-update-cmd section of your composer.json.

That last suggestion is the practical one. elFinder is a JavaScript application with its own assets, and a Composer update that changes the elFinder version without republishing leaves the browser running an older script against a newer server, which produces failures that look like application bugs rather than version skew. Wiring it into post-update-cmd makes the mismatch impossible.

Routes are added by the ElfinderServiceProvider, and you set the group parameters for them in the configuration. The README says you can change the prefix and the filter or middleware for the routes, and that for full customisation you can extend the service provider and override the map() function.

The default configuration expects a directory called files in the public folder. To change that, publish the config file:

bash
php artisan vendor:publish --provider='Barryvdh\Elfinder\ElfinderServiceProvider' --tag=config

That creates config/elfinder.php, where you can change the default folder, the access callback, or define your own roots.

The access callback deserves attention because it is the security boundary. elFinder is a file browser, and the callback decides which parts of the disk a user may see and write. The default assumes a public directory, which is fine for a demo and wrong for anything holding user uploads.

Views and asset versioning

The default views can be overridden by copying the resources/views folder, and the README gives the vendor:publish command for it:

bash
php artisan vendor:publish --provider='Barryvdh\Elfinder\ElfinderServiceProvider' --tag=views

The reason to override is that the views are what your users see when they open the file manager, and the default is a bare elFinder interface. Overriding it means you can put your own chrome around the picker, which matters when it appears inside an editor rather than on an admin page.

The asset linking has a detail that solves a real problem. The views link to the published assets with AssetHelper::asset(), which appends a version to the URL based on the installed versions of studio-42/elfinder and this package:

blade
<script src="{{ \Barryvdh\Elfinder\AssetHelper::asset($dir, 'js/elfinder.min.js') }}"></script>

The $dir argument is the publish directory, relative to the public path.

Appending a version to the URL is what makes browsers pick up the new files after you re-publish. Without it, the browser keeps the cached copy of elfinder.min.js, and since the file name never changes, a cached copy is served indefinitely unless the user hard-reloads. That is the second half of why the publish step matters: publishing without a versioned URL gives you a file on disk that the browser will not fetch.

Together, the publish command and the versioned URL are the two halves of the same mechanism. One puts the new bytes on disk, the other makes the browser ask for them.

Tests, versions and what to check before shipping

The test suite runs against Laravel 9 through 13 with Testbench, which is the package that lets a Laravel package be exercised inside a throwaway application rather than a full one. The command is:

bash
composer test

Running against that range of framework versions is the useful signal, because a package that wires itself into the service provider, config publishing and route registration is exactly the kind that breaks on a major framework release. A matrix spanning four majors is evidence that this one does not.

Two version facts to hold on to. The current line is 0.6, and for Laravel 8.x and older you are told to use the latest 0.4 version, so the package maintains parallel lines for old and new framework versions. And the version numbers are low, which under the usual conventions means the API can still change.

Before you ship this into an application, there are four things worth checking in order.

First, the access callback. The default configuration expects a directory called files in the public folder, and the callback decides what a user may reach. A file browser whose roots are a public directory will show everything in it, including files you did not intend to expose. Read config/elfinder.php and replace the default callback with one that checks the authenticated user.

Second, the route middleware. The README says the routes are registered by the service provider and that you can set the prefix and the filter or middleware for them. A file manager that is publicly reachable is a serious problem, and the default may not be what you want.

Third, the published assets. If you are upgrading an existing install, publish again. The versioned asset URL means the browser will fetch the new script, but only if the new script is on disk.

Fourth, the disks you expose. Mounting an S3 disk as an elFinder root means the picker can write to that bucket, with whatever credentials the disk uses. That is a privilege worth deciding on deliberately.

Disks, Glide thumbnails and the editor integrations

The most substantive feature in this package is the disks configuration, and it is what distinguishes it from a plain elFinder install.

Laravel can use Flysystem adapters as local or cloud disks, and the elfinder disks config lets you add those to the manager:

php
'disks' => [
    'local',
    'my-disk' => [
        'URL' => url('to/disk'),
        'alias' => 'Local storage',
    ]
],

A bare string uses the disk with its own defaults, and an array gives extra options such as the URL and an alias. If you do not provide a URL, the README says it is generated by the disk itself. That is how the same file manager can browse a local public directory and an S3 bucket, because both are Laravel disks.

Glide support comes through a separate package, barryvdh/elfinder-flysystem-driver. The README walks through a five-step setup: configure a public disk with a local driver rooted at base_path().'/public', register a Glide server on a glide/<path> route with a cache path, then add the disk to the elfinder config with a glideURL pointing at that route:

php
'disks' => [
    'public' => [
        'glideURL' => '/glide',
    ],
],

The optional step is adding a glideKey to the config and verifying the key in the Glide route using the Glide HttpSignature, which is the mechanism that stops anyone generating thumbnails for arbitrary paths.

The result is that elFinder shows a public root with thumbnails generated by Glide, and the image URLs point at the Glide server rather than the original file.

The editor integrations are the other half of the package's purpose. For TinyMCE 5.x there is a route at /elfinder/tinymce5, obtained with route('elfinder.tinymce5'), and in the TinyMCE init code you add the line file_picker_callback : elFinderBrowser. The JavaScript function opens the elFinder window through the TinyMCE window manager with an onMessage handler that reads the selected file and calls the callback with the URL and, depending on whether the media type is file, image or media, the appropriate text, alt or bare URL. TinyMCE 4.x has its own route at /elfinder/tinymce4. The README also mentions example views for CKEditor and standalone use.

Where this fits against the alternatives

The alternative to a full file manager is a plain file picker, and for a lot of applications that is the better answer. If your users need to attach one image to a form, a styled input with a preview does the job, has no directory browsing to secure, and does not need an elFinder instance in the page.

The alternative to elFinder itself is another web file manager. There are several, and the reasons to prefer this one are mostly Laravel specific rather than about the file browsing: the assets are published by an artisan command, the routes are registered by a service provider, the roots are Laravel disks so the same code browses local and cloud storage, and there are ready-made integrations for the editors people actually use.

What this package does not do is multi-user isolation with per-user credentials. elFinder has a single connection and a single set of roots, so every user of the manager sees the same files. If your requirement is a private drive per user, you need either a different tool or a per-user deployment of the connector, and that is a significant piece of work rather than a configuration change.

There is also the question of whether a file manager is needed at all. If the application only ever writes to a fixed location and shows the result, a published assets directory and a signed upload endpoint is a smaller design.

Editorial conclusion

Adopt laravel-elfinder if your Laravel application needs a browsable file picker or a small file manager and you want the browsable roots to be Laravel disks rather than raw folders. Skip it if you need multi-tenant isolation with per-user credentials, since the connection model is a single configured session. Verify first by publishing the assets, adding the disk to the elfinder disks config, and confirming the picker opens the root and that the access callback applies to it.

Frequently asked questions

How do I install laravel-elfinder and publish its assets?

Run composer require barryvdh/laravel-elfinder, then php artisan elfinder:publish to copy the assets into the public folder. The README says to publish after each update, or to add that command to the post-update-cmd section of your composer.json.

Where do the elFinder files come from in laravel-elfinder?

They are not vendored into the repository. The PHP files come through Composer with autoloading and are updated from a separate build repository, barryvdh/elfinder-builds, with studio-42/elfinder as the underlying package. That is why the assets must be re-published after each update.

Can elFinder browse S3 or other Laravel disks?

Yes. Laravel exposes Flysystem adapters as local and cloud disks, and the disks config in config/elfinder.php accepts either a disk name as a string or an array with extra options such as a URL and an alias. If no URL is given it is generated by the disk itself.

How does laravel-elfinder handle thumbnails?

Through a separate package, barryvdh/elfinder-flysystem-driver, which uses Glide to generate them. You register a Glide server on a route, add the disk to the elfinder config with a glideURL pointing at it, and can optionally add a glideKey verified with the Glide HttpSignature.

How do I use elFinder as a TinyMCE file picker?

Use the route elfinder.tinymce5 for TinyMCE 5.x or elfinder.tinymce4 for TinyMCE 4.x, then add file_picker_callback : elFinderBrowser to the TinyMCE init code. The example JavaScript opens the picker through the TinyMCE window manager and handles the fileSelected message to return the URL.

Official sources

  1. barryvdh/laravel-elfinder on GitHub
  2. Issues
  3. README
  4. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/barryvdh-laravel-elfinder.svg)](https://hysenlabs.com/projects/barryvdh-laravel-elfinder)

Was this useful?