Install the Bundle
composer require helios-ag/fm-elfinder-bundle
Enable in config/bundles.php:
return [
// ...
HeliosAg\FMElfinderBundle\FMElfinderBundle::class => ['all' => true],
];
Configure Routes
Add to config/routes.yaml:
fm_elfinder:
resource: "@FMElfinderBundle/Resources/config/routing.yml"
prefix: /elfinder
Basic Usage Include the JS/CSS in your template:
{{ include('@FMElfinder/elfinder.html.twig', {
id: 'elfinder',
lang: 'en',
url: path('fm_elfinder')
}) }}
Trigger via:
$('#elfinder').elfinder({
url: '/elfinder/connector'
});
First Use Case Integrate with a WYSIWYG editor (e.g., TinyMCE) for file uploads:
tinymce.init({
selector: 'textarea',
plugins: 'filemanager',
filemanager_callback: function(callback, value, meta) {
$('#elfinder').elfinder('open', function(elfinder) {
elfinder.callbacks.open.call(elfinder, callback, value, meta);
});
}
});
File Management Integration
FMElfinderBundle's built-in connectors for Symfony file systems (e.g., Flysystem, Symfony Filesystem).config/packages/fm_elfinder.yaml:
fm_elfinder:
instances:
default:
connector: 'fm_elfinder.connector.filesystem'
root: '%kernel.project_dir%/public/uploads'
Custom Connectors
Extend FMElfinderBundle\Connector\AbstractConnector for database-backed storage or cloud services (e.g., S3):
namespace App\Connector;
use FMElfinderBundle\Connector\AbstractConnector;
class S3Connector extends AbstractConnector {
public function init() {
$this->driver = 'S3';
$this->volume = new \League\Flysystem\AwsS3v3\AwsS3Adapter(...);
}
}
Register in services:
services:
app.elfinder.connector.s3:
class: App\Connector\S3Connector
tags: ['fm_elfinder.connector']
Permissions & ACLs Use Symfony’s security component to restrict access:
fm_elfinder:
instances:
admin:
connector: 'fm_elfinder.connector.filesystem'
root: '%kernel.project_dir%/public/admin-uploads'
access_control: 'ROLE_ADMIN'
In Twig:
{% if is_granted('ROLE_ADMIN') %}
{{ include('@FMElfinder/elfinder.html.twig', { id: 'admin-elfinder' }) }}
{% endif %}
Event-Driven Extensions Listen to file events (e.g., upload, delete) via Symfony events:
// config/services.yaml
App\EventListener\ElfinderEventListener:
tags:
- { name: kernel.event_listener, event: fm_elfinder.pre_upload, method: onPreUpload }
elFinder JS/CSS with your app’s assets.translations/messages.en.yaml:
fm_elfinder:
dialog:
title: 'Custom File Manager'
assets/elfinder/css/elfinder.min.css or override templates in templates/bundles/FMElfinder/.CORS Issues
If using elFinder in a SPA or cross-domain context, ensure:
/elfinder/connector) has proper CORS headers.AccessControl for OPTIONS requests:
# config/packages/security.yaml
access_control:
- { path: ^/elfinder/connector, roles: PUBLIC_ACCESS }
File System Permissions
root directory in fm_elfinder.yaml is writable by the web server user (e.g., www-data).chmod -R 775 %kernel.project_dir%/public/uploads
chown -R www-data:www-data %kernel.project_dir%/public/uploads
Connector Caching
php bin/console cache:clear
JavaScript Conflicts
elFinder relies on jQuery and jQuery UI. Load them before elFinder:
{{ include('FMElfinder::jquery-ui.html.twig') }}
{{ include('@FMElfinder/elfinder.html.twig') }}
debug: true in fm_elfinder.yaml to log connector requests.var/log/dev.log for errors like:
[FMElfinderBundle] Connector error: "File not found" (code: 2)
curl to test the connector endpoint:
curl -X POST http://localhost/elfinder/connector -d 'cmd=open&target='
Custom Commands
Add new elFinder commands (e.g., "Compress") by extending the connector:
public function init() {
$this->commands = array_merge($this->commands, [
'compress' => [$this, 'handleCompress'],
]);
}
UI Customization
Override Twig templates (e.g., elfinder.html.twig) in templates/bundles/FMElfinder/.
Example: Add a custom toolbar button:
{# templates/bundles/FMElfinder/elfinder.html.twig #}
<button id="custom-button" class="elfinder-button">Custom Action</button>
Database Metadata
Store file metadata (e.g., title, description) in a database table and hydrate it via a custom connector:
public function open($path, $options = []) {
$files = $this->fetchFilesFromDB($path);
return $this->formatFiles($files);
}
Lazy Loading For large directories, implement lazy loading in the connector:
public function open($path, $options = []) {
if (strpos($path, 'large-folder') !== false) {
return $this->streamFiles($path); // Stream files on demand
}
return parent::open($path, $options);
}
root in fm_elfinder.yaml must be an absolute path (e.g., %kernel.project_dir%/public/uploads).path() in Twig to generate the connector URL:
url: "{{ path('fm_elfinder') }}"
instances in fm_elfinder.yaml for different use cases (e.g., admin vs. user uploads). Access them via:
$('#elfinder-admin').elfinder({ url: '/elfinder/connector?instance=admin' });
How can I help you explore Laravel packages today?