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

File Repository Bundle Laravel Package

modera/file-repository-bundle

Modera File Repository Bundle offers a configurable file repository abstraction for Symfony applications, simplifying storage, retrieval, and management of uploaded files through reusable repository services.

View on GitHub
Deep Wiki
Context7

Getting Started

First, the reality check: modera/file-repository-bundle is a Symfony bundle, not a Laravel package. There is no service provider, no facade, no config/file-repository.php. If you are working in a Laravel codebase, you cannot composer require this and expect it to boot — you would need to either (a) run it inside a Symfony app that exposes an API your Laravel app consumes, or (b) port the idea (a files table + a storage abstraction) into Laravel using Storage and Eloquent. The rest of this assessment assumes you are actually in a Symfony 2.x/3.x-era project, because that is the only context where the bundle runs.

Installation in that context:

composer require modera/file-repository-bundle

Then register the bundle in app/AppKernel.php:

$bundles = [
    // ...
    new Modera\FileRepositoryBundle\ModeraFileRepositoryBundle(),
];

Update your Doctrine schema so the bundle's File entity table is created (doctrine:schema:update --force or generate a migration), then confirm the repository service is wired:

bin/console debug:container | grep -i file_repository

The first use case to validate end-to-end is the "store then reference" flow: take an UploadedFile from a form, push it through the repository service, and persist only the returned file's identifier on your own entity. That single loop exercises storage config, Doctrine mapping, and the retrieval path — if it works, the rest of the bundle is mostly variations on it.

Where to look first: the bundle's README.md, its Resources/config/services.xml (service IDs and class names — the documented API is thin, so the DI config is the real spec), and the bundled File entity mapping under Resources/config/doctrine/.

Implementation Patterns

Store binary outside your domain entity. The core value of the bundle is decoupling file bytes from business entities. Your Product, Invoice, or Avatar entity holds a scalar foreign key (file id), not a blob column and not a filesystem path:

// in a controller / handler
$stored = $fileRepository->store($request->files->get('avatar'));
$user->setAvatarFileId($stored->getId());
$em->flush();

Verify the exact method names against services.xml — the repository interface is small (store / get / delete is the conceptual surface), but this is a 2016 bundle and naming is not guaranteed to match modern expectations.

Wrap storage in your own thin adapter. Because the bundle is unmaintained, hide it behind an interface you own:

interface AvatarStore {
    public function put(UploadedFile $file): string;   // returns your id
    public function url(string $id): string;
    public function forget(string $id): void;
}

Then a ModeraAvatarStore implements it today, and swapping to Flysystem/Gaufrette/S3 later is a one-class change. This is the single highest-leverage pattern for a low-adoption dependency.

Tie deletion to entity lifecycle. The common failure mode is orphaned files (entity deleted, bytes retained) or dangling references (bytes deleted, entity still points at them). Pick one owner of the lifecycle: a Doctrine postRemove listener on your entity that calls forget(), or a scheduled garbage-collection job that diffs files table ids against referencing rows. Do not do both without idempotency.

Serving downloads belongs in a controller, not a public path. Expect (or add) a controller action that resolves the id through the repository and returns a StreamedResponse with the stored mime type and a Content-Disposition header. If the bundle ships a download route, confirm it is behind your firewall — a repository that serves files by sequential integer id is enumeration-friendly.

Replacement is store-new-then-swap. To replace an attachment, store the new file, update the FK, flush, then delete the old id. Doing it in the other order loses data if the flush fails.

Testing: point the storage layer at a temp directory (or in-memory DB blob, depending on which backend you configure) in config_test.yml, and assert on the id round-trip rather than on filesystem layout. Never let tests write into web/uploads.

// illustrative
$id = $store->put(new UploadedFile($tmp, 'a.png', 'image/png'));
$this->assertSame('image/png', $repo->get($id)->getMimeType());

Gotchas and Tips

  • Unmaintained since 2016 (3 stars, 0 dependents). Treat it as vendored code you now own. Pin the version, fork it internally, and expect zero upstream fixes. PHP and Symfony version constraints in its composer.json will likely block a modern Symfony upgrade — check before committing to it.
  • No Laravel bridge exists and none is coming. If the goal is a Laravel project, skip the package entirely; Storage::disk('s3')->put() plus a files table (id, disk, path, mime, size, checksum) gets you 90% of the behavior with first-class framework support.
  • Service IDs are undocumented. debug:container and services.xml are the source of truth. Compiler passes in ModeraFoundationBundle (a common sibling dependency) can also affect wiring.
  • Doctrine auto-mapping collisions. If your app uses auto_mapping: true, the bundle's entity can collide with an entity of the same short name in your own bundle. Scope mappings explicitly.
  • DB-blob vs filesystem trade-off. If the configured storage writes bytes into the database, your backups, replication, and SELECT * queries all get heavier. Prefer filesystem/object storage for anything above small thumbnails.
  • Transaction boundaries. A store happens outside the DB transaction that saves your entity. On rollback you get an orphan file; on a crash between store and flush you get the same. A periodic orphan sweep is cheaper than trying to make storage transactional.
  • Mime type and filename are attacker-controlled. Validate mime type server-side (don't trust the client's Content-Type), and never reflect the original filename into a filesystem path or a raw Content-Disposition header without sanitizing.
  • Enumeration. Sequential integer ids on a download route leak volume and allow scraping. If files are sensitive, add an unguessable token column or gate the route with a policy check on the owning entity.
  • Extension points: the clean seams are (1) a custom storage backend implementing the bundle's storage interface, and (2) decorating the repository service in your services.yml to add validation, virus scanning, or image resizing on store. Both survive a future replacement of the bundle far better than editing it in place.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console