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

Filelib Bundle Laravel Package

xi/filelib-bundle

XI FileLib Bundle brings a flexible file library to Symfony applications, offering storage abstraction, upload handling, and metadata management for uploaded files. Configure storage backends, attach files to your Doctrine models, and serve them consistently across your project.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony 2-era bridge, so the first job is establishing whether it will install at all before writing feature code.

composer require xi/filelib-bundle --dry-run   # see what it resolves to first
composer why-not xi/filelib-bundle

Check two things before anything else: the package's PHP constraint (the underlying xi/filelib is PHP 5.3-era code and will almost certainly fail on PHP 8) and whether the bundle's composer.json pins a Symfony major version. If you are on Symfony 2.8 you may be fine; on anything newer, plan on forking or not using it.

Minimal setup in a Symfony 2 app:

  1. Register the bundle in app/AppKernel.php — copy the FQCN from the bundle's *Bundle.php file rather than guessing it.
  2. Add a xi_filelib: block to app/config/config.yml.
  3. Confirm the generated service ids.
// app/AppKernel.php
$bundles = array(
    // ...
    new Xi\Bundle\FilelibBundle\XiFilelibBundle(),
);
# app/config/config.yml
xi_filelib:
    backend:
        type: doctrine_orm      # or filesystem / mongodb
    storage:
        type: filesystem
        path: "%kernel.root_dir%/../web/uploads"
    publisher:
        type: local
        path: "%kernel.root_dir%/../web/media"

The configuration tree in DependencyInjection/Configuration.php is the authoritative reference — the keys above are the shape you should expect (backend / storage / platform / publisher / profiles), but the exact names are whatever that file declares. Read it before writing config; there is effectively no documentation, so the Configuration class is the docs.

Then verify what actually got registered:

app/console container:debug | grep -i filelib

You are looking for the main FileLibrary service plus its collaborators (FileManager, FolderManager, FileUploader). Note the exact ids — you will inject them for the rest of the project's life.

First use case: upload a file in a controller and render a link to it. That single flow exercises backend, storage, and publisher at once and will surface 90% of the configuration problems immediately.

public function uploadAction(Request $request)
{
    /** @var \Xi\Filelib\FileLibrary $filelib */
    $filelib = $this->get('xi_filelib'); // confirm id via container:debug

    $file = $filelib->getFileManager()->upload(
        new \Xi\Filelib\File\Upload\FileUpload($request->files->get('file')->getPathname())
    );

    return $this->redirect($filelib->getPublisher()->getUrl($file));
}

Implementation Patterns

Keep the library out of controllers. Wrap it in one application service so the dependency is isolated in a single class you can later reimplement on top of Flysystem or Vich. This is the single highest-leverage decision you will make with this package, because the exit cost is otherwise spread across every controller.

class MediaManager
{
    private $filelib;
    private $fileManager;

    public function __construct($filelib)
    {
        $this->filelib = $filelib;
        $this->fileManager = $filelib->getFileManager();
    }

    public function store(UploadedFile $upload, $folderId = null)
    {
        $upload = new FileUpload($upload->getPathname());
        return $this->fileManager->upload($upload);
    }
}

Learn the four-way split early. Filelib distinguishes backend (metadata/records), storage (raw bytes), platform (local/S3/Dropbox-ish abstraction), and publisher (public-facing copies and derivative URLs). Most confusion comes from conflating storage with publisher: a file can be successfully stored and still be unreachable over HTTP because it was never published. When "the file is there but the URL 404s," check the publisher configuration first.

Use profiles for derivatives. Define a base profile (e.g. original, thumb, medium) in config rather than generating sizes ad hoc. Then request versions through the FileLibrary API instead of storing your own thumbnail paths in the database. This is where the package earns its keep — you get consistent derivative generation across uploads and a single place to change dimensions later.

Hook the library's events instead of post-processing in controllers. Filelib dispatches events around upload/publish/delete. Register a Symfony listener for the after-upload event and use it for the things you will inevitably need: stripping EXIF, virus scanning, pushing to a CDN, or writing an audit row. Keeping that logic in a listener means it also runs for CLI imports and admin uploads.

Test against in-memory implementations. Filelib ships memory-backed backend/storage/publisher variants. Wire those in config_test.yml so functional tests never touch the real filesystem — filesystem tests are the number-one source of flaky, order-dependent suites.

# app/config/config_test.yml
xi_filelib:
    backend: { type: memory }
    storage: { type: memory }
    publisher: { type: memory }

Treat CLI as a first-class workflow. Bulk import and orphan cleanup are the two jobs you will write immediately. Put them in a Symfony command that resolves the app-level MediaManager, not the FileLibrary service directly, so they survive a future swap.

Serve through a controller when files are private. The local publisher writes into a web-reachable directory, which is fine for public media and wrong for anything user-private. For private assets, skip the publisher URL and stream the file from a controller after an authorization check.

Gotchas and Tips

Adoption risk is the headline. Four stars, zero dependents, and a Symfony 2 target that hit end-of-life in 2019. There is no ecosystem of answers, no Stack Overflow corpus, and no maintainer to file issues against. Budget for forking the bundle into your own vendor namespace on day one — it is small, and you will be patching it.

PHP compatibility will bite before anything else. Old constraint syntax, deprecated each()/mcrypt-era idioms, and missing return types. Run the full test suite on your target PHP version before planning around this; if it fails on load, the assessment is over and you should go straight to Vich or OneupFlysystemBundle.

The Doctrine backend needs its own schema. File and folder metadata live in tables that the bundle does not necessarily create via migrations. Check for a Resources/config/doctrine mapping, generate a migration, and confirm the tables exist before debugging application code — "file not found" errors often mean the metadata row was never persisted because the table is missing.

Permissions on the storage and publisher roots. Both directories must be writable by the web user. On shared hosting or Docker volumes this is the most common first failure, and the resulting exception is not obviously about permissions.

Deleting the entity does not delete the bytes. Removing a File record and removing the stored file are separate operations. Without an explicit cleanup job you will accumulate orphaned files indefinitely. Write the cleanup command early, and log every delete path.

Image processing is memory-hungry. Derivative generation via Imagine/GD will exhaust the default memory_limit on any modern camera JPEG. Set the limit per-request or move derivative generation to a queued listener rather than doing it synchronously in the upload request.

Never build paths from user input. FileUpload takes a pathname; validate that it comes from UploadedFile::getPathname() and nothing else. Sanitize filenames, and enforce both an extension allowlist and a MIME sniff before the file reaches the library.

Config changes require a container rebuild. In the dev environment a stale cache after editing the xi_filelib block produces confusing "service not found" errors. app/console cache:clear before investigating anything else.

Extension points, in order of usefulness: custom Platform (the path to S3 or a CDN — check whether the bundle ships only a local one), custom Storage, and custom Backend. Register each as a Symfony service and reference it by id in config; that is the sanctioned way to extend without forking core files. Everything else — profiles, publishers — is configuration.

Debug with container:debug and the library's own exception types. FileNotFoundException, publishing failures, and backend errors are distinct exception classes; catching and logging the class name will tell you which of the four layers failed far faster than reading stack traces through the bundle's service wiring.

Have an exit plan. Write a single MediaManager interface in your app (store, url, delete, exists) and implement it once against Filelib. When you migrate — and with a package in this state, it is a question of when — you change one class instead of grepping the codebase for getFileManager().

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager