krma-cl/kcfinder
Laravel integration for KCFinder, providing a browser-based file manager for uploading, browsing, and selecting images or files in CKEditor and other WYSIWYG editors. Includes configuration and helper hooks to wire KCFinder into your PHP app.
Install the release with Composer and point the web server at the package's entry point:
composer require krma-cl/kcfinder:^4.10
KCFinder is not a Laravel service provider package — it is a self-contained PHP file manager/browser that you expose from public/ (or a symlinked public/vendor/kcfinder) and configure through its own config file. First places to look:
conf/config.php (or your uploaded override) — uploadDir, uploadURL, types, deniedExts, session settings, and the new dragMove block.VERSION at the package root — the single source of truth for the version shown in the UI and exposed to HTTP clients. Keep it intact when deploying.kcfinder-bootstrap5-theme v0.4.0) if you want the UI to match a Bootstrap 5 admin panel.Minimal Laravel wiring for a first use case — a per-user asset browser behind the CKEditor/TinyMCE "Browse Server" button:
// config/filesystems.php
'kcfinder' => [
'driver' => 'local',
'root' => storage_path('app/public/uploads'),
'url' => env('APP_URL').'/storage/uploads',
],
// routes/web.php
Route::get('/kcfinder/{any?}', fn () => response()->file(public_path('vendor/kcfinder/browse.php')))
->where('any', '.*')->middleware('auth');
Then in your editor config: filebrowserBrowseUrl = '/kcfinder/browse.php?type=files'.
First use case to validate end-to-end: upload a file from the browser, confirm it lands in storage/app/public/uploads, and confirm the storage symlink serves the thumbnail. Leave dragMove.enabled off until the rest works — moving is opt-in in this release.
Bridging Laravel auth into KCFinder. KCFinder runs outside the Laravel kernel, so it can't see Auth::user(). The reliable pattern is to have KCFinder read a session key you set on login:
// In your LoginController
session(['kcfinder_user' => $user->id]);
and map that to a per-user uploadDir (.../users/{id}) in the KCFinder config. Avoid sharing Laravel's session cookie wholesale — configure KCFinder's own session name/handler so the two don't clobber each other.
Observing moves for Laravel events. v4.10's neutral operation observer is the cleanest integration point. Register a callback that receives the previous and resulting logical paths (i.e. paths relative to the configured upload root, not filesystem absolute paths) and dispatch a domain event:
$kcfinder->observeOperations(function (string $type, string $from, string $to) {
if ($type === 'move') {
event(new FileMoved($from, $to)); // update DB references, clear CDN cache, etc.
}
});
Because paths are logical, you can map them straight onto a media table's path column without normalising against storage_path().
Drag-and-drop move workflow. Enable it deliberately and scope the UI to trusted roles — moving is a destructive-ish operation that a mis-drop can trigger:
'dragMove' => [
'enabled' => true, // must be explicit; default is false
],
Pair it with the accessible Move to… context-menu action in your admin screens; it is keyboard-reachable and is the fallback you should document for users who can't drag.
Conflict resolution as an application decision. The new whole-operation conflict prompt (overwrite / keep both / cancel) covers a batch, not per-file. If your users routinely move into populated folders, decide up front which default you want and communicate it: "keep both names" is the safe default for user content, "overwrite" only for a machine-managed asset folder.
Theming without forking. Use the validated themeOptions semantic palette rather than editing Composer-installed theme files — this survives composer update:
'themeOptions' => [
'primary' => '#0d6efd',
'surface' => '#f8f9fa',
// only semantic roles are accepted; arbitrary CSS is rejected
],
Version reporting. Read VERSION for support tooling and health checks — expose it on an admin diagnostics page and compare against the installed Composer constraint so you notice a stale traditional ZIP install.
dragMove.enabled must be set explicitly to true. If users report "drag does nothing" after upgrading, this is the first thing to check — it is intentional, not a regression.themeOptions is validated, not sanitised. Invalid semantic colors are rejected rather than coerced; check the response/logs if a theme update silently renders default colors. You cannot inject raw CSS through it — that is a feature, not a limitation.Storage::disk() assuming they're absolute. Prefix with your configured root, and remember moves change the path — update any stored references transactionally or you get broken thumbnails.VERSION is shared state. The UI, HTTP clients and release archives all read the same root file. Don't strip it in your Docker COPY/.dockerignore or in a post-deploy rm of docs — the UI will lose its version and diagnostics lie.composer update, clear OPcache and bump your static asset query string, or users get a v4.9 UI talking to a v4.10 backend.deniedExts for your application's upload policy, and ensure uploadDir never resolves inside app/ or config/.localhost vs 127.0.0.1). If the browser silently loses auth, check the session cookie paths before anything else.How can I help you explore Laravel packages today?