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

Kcfinder Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

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:

  1. conf/config.php (or your uploaded override) — uploadDir, uploadURL, types, deniedExts, session settings, and the new dragMove block.
  2. 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.
  3. The theme integration (e.g. 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.

Implementation Patterns

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.

Gotchas and Tips

  • Moving is off by default. 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.
  • Don't build on trash or visual ordering. Both are documented as future work and are not enabled or implemented in 4.10. Any UI copy promising undo/restore is wrong for this release.
  • 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.
  • Observer payloads are logical paths. Don't pass them to 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.
  • Upgrades need a real cache bust. PHP file managers are asset-heavy and often served with long-lived cache headers. After composer update, clear OPcache and bump your static asset query string, or users get a v4.9 UI talking to a v4.10 backend.
  • Traditional ZIP installs don't self-update. If you deploy via the verified ZIP rather than Composer, record the checksum and add a deploy-time version check; otherwise you drift and lose the advisory audit coverage the Composer path gives you.
  • Path traversal and denied extensions are config, not defaults you can trust blindly. Re-audit deniedExts for your application's upload policy, and ensure uploadDir never resolves inside app/ or config/.
  • Session isolation. KCFinder's session handling frequently collides with Laravel's cookie name/domain in local development (localhost vs 127.0.0.1). If the browser silently loses auth, check the session cookie paths before anything else.
  • Debugging moves: reproduce with the Move to… menu action rather than drag — it removes the pointer/DOM layer from the equation and tells you immediately whether the problem is backend conflict resolution or the UI.
  • Test surface is broad but not yours. 109 tests across PHP 8.2–8.5 cover the package; your per-user directory mapping, observer wiring and theme config are untested. Add a feature test that performs an upload and a move through the actual entry point as part of your upgrade gate.
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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log