servocoder/richfilemanager
Laravel integration for RichFilemanager, a responsive web-based file manager. Browse, upload, edit, and manage files and folders through a clean interface, with support for images, documents, and configurable storage backends. Easy to install and customize.
Install and publish in one pass, then confirm what actually landed on disk before touching any config.
composer require servocoder/richfilemanager
php artisan vendor:publish --provider="Servocoder\RichFilemanager\RichFilemanagerServiceProvider"
On Laravel <5.5 also register the provider in config/app.php and, if you want the facade, add the alias. The publish step should produce a package config (typically config/richfilemanager.php) and a public asset bundle for the JS/CSS frontend.
Look first at three things:
php artisan route:list | grep -i richfilemanager shows the page route and the JSON connector endpoint it talks to. Note whether they're in the web group (you almost always want them to be, for session + CSRF).public/vendor/... — if the browser renders a blank shell or 404s on JS, publishing assets failed or the view is resolving a stale path.Minimum viable setup
root/upload path at a directory the PHP process can write to (e.g. storage/app/public/files), and create it.storage/app/public is linked (php artisan storage:link) if you plan to serve uploaded files via the public disk.['web', 'auth'] so Auth::user() is populated for access control.First real use case: an admin-only media library. Put the route behind auth plus a role gate, then link it from a CMS page editor as "Browse media" (open in a popup or iframe). The editor picks a file, you persist the returned relative path, and render it later with Storage::url() or asset().
Gate the route, not the UI. The frontend hides buttons based on capabilities, but that's cosmetic. Put authorization in middleware and in the server-side ACL/capability checks the package exposes. A pattern that scales:
// config/richfilemanager.php
'middleware' => ['web', 'auth', 'can:manage-media'],
or a dedicated middleware that checks tenant/role and aborts with 403 before the connector runs.
Per-user / per-tenant roots. Because the config is static, override it in a middleware that runs before the package route, keyed off the authenticated user:
public function handle($request, Closure $next)
{
$tenant = $request->user()->tenant;
abort_unless($tenant, 403);
config([
'richfilemanager.root' => storage_path("app/tenants/{$tenant->id}/files"),
// adjust whatever key the published config actually uses
]);
return $next($request);
}
Never derive the root from a request parameter — that's the path-traversal hole in this class of package.
WYSIWYG integration is the bread-and-butter workflow. Configure CKEditor/TinyMCE to open the file manager as a picker and return the chosen URL:
// CKEditor
config.filebrowserBrowseUrl = '/richfilemanager?type=1';
config.filebrowserUploadUrl = '/richfilemanager?type=1';
For TinyMCE use file_picker_callback and either iframe the manager or call its JSON API directly. Keep the dialog same-origin so window.opener/postMessage back to the editor works — cross-origin iframes break this silently.
Store relative paths, resolve late. Persist files/2024/hero.jpg in the DB and call Storage::url() at render. Storing absolute URLs bakes in your domain, CDN, and environment.
Let the package own uploads. Resist building a parallel upload endpoint. The file manager already handles chunked/browser uploads, thumbnails, and rename/move. Your app should only read the resulting paths.
Testing pattern. Feature-test the route rather than the JS:
$this->actingAs($user)->get('/richfilemanager')->assertOk();
$this->actingAs($guest)->get('/richfilemanager')->assertForbidden();
For destructive operations (delete/move), hit the JSON connector with a CSRF token in a test and assert the file exists/doesn't on disk — that catches root misconfiguration that the UI won't reveal.
Production storage. RichFilemanager is a local-filesystem tool; if you need S3, mount/sync the bucket to local disk and point the root there, or accept that this package is not the right fit for remote object storage.
composer why-not servocoder/richfilemanager before assuming it installs on modern Laravel. On Laravel 9+/PHP 8 expect to fork it (null-coalescing, removed each(), dynamic properties) or switch to a maintained alternative like unisharp/laravel-filemanager.web middleware group. Conversely, if you're embedding in an iframe on a different host, SameSite cookie settings will drop the session and every request looks unauthenticated.auth without web. Listing auth before web means no session is started, Auth::user() is null, and your ACL check fails in a way that looks like a permissions bug but is a middleware-order bug.php artisan config:cache freezes the config; any dynamic config([...]) override must happen at request time in middleware (not at boot), and env() calls must live only in config files — never inside the package's runtime code paths.php artisan route:cache. If deploy fails, check route:list / the package's route file and replace closures with controller actions in a fork.laravel.log at debug=false is usually the web user lacking write access to the target directory, or an SELinux context denying writes. Verify with sudo -u www-data touch <root>/test.upload_max_filesize, post_max_size, max_execution_time, and NGINX client_max_body_size all need raising together. Large-image thumbnailing can also hit max_execution_time; test with a 10MB+ JPEG, not a 40KB PNG.security.extensions / patterns in config. Don't trust the frontend capability flags to block .php uploads.public/. If you point the root under the web root, the OS may serve files directly, bypassing your middleware. Decide deliberately: private root + controller delivery, or public root + symlink. Don't get both by accident.curl including the session cookie and X-CSRF-TOKEN; that isolates "frontend bug" from "server config bug" fast.composer.lock is your friend; upstream changes are unlikely and a surprise fork merge is worse than a stale pin.How can I help you explore Laravel packages today?