oro/gridfs-config
Oro GridFS Config provides configuration support for integrating MongoDB GridFS storage into Oro/Laravel applications, simplifying connection, bucket, and file-storage settings for managing large files consistently.
OroGridFsConfigBundle is a thin integration bundle: it does not implement GridFS itself, it wires a GridFS filesystem adapter into Oro's oro_filesystem configuration layer so that files managed by Oro (attachments, public/private files, import/export dumps) can be stored in MongoDB GridFS instead of on local disk or S3.
Prerequisites
ext-mongodb (the modern driver, not the legacy ext-mongo) and mongodb/mongodb.league/flysystem at the major version the bundle was built against (v1 is most likely). Confirm via the package's composer.json before installing.Minimal steps
composer require oro/gridfs-config and inspect what it pulls in — the actual adapter dependency is the thing you really care about.config/bundles.php on Symfony 4/5-style apps, or AppKernel::registerBundles() on older OroPlatform).php bin/console cache:clear then php bin/console debug:container --tag=... / debug:container | grep -i gridfs to see which services the bundle actually registers.config/config.yml (see the pattern below) and point one non-critical filesystem — e.g. attachments in a dev environment — at it.use oro_gridfs
db.fs.files.find().sort({uploadDate: -1}).limit(1)
db.fs.chunks.countDocuments({ files_id: <id> })
Where to look first
DependencyInjection/ — the extension and Configuration.php tell you the exact config keys the bundle accepts. That is the real API surface.Resources/config/ — service definitions, adapter factory, and any Resources/config/oro/*.yml that hooks into system configuration or the filesystem registry.oro_filesystem adapters) and the Flysystem GridFS adapter's own README, since most behaviour/bugs come from those, not from this bundle.composer.json — dependency pins are the single best predictor of whether this will install cleanly in 2024-era apps.Config-driven adapter registration
The bundle's job is to let you declare a GridFS-backed adapter in Oro's filesystem config. The shape will resemble:
# config/config.yml
oro_filesystem:
adapters:
gridfs:
# keys come from the bundle's Configuration.php — verify, do not guess
uri: '%env(MONGODB_URI)%'
database: '%env(MONGODB_DB)%'
bucket: 'oro_files'
filesystems:
attachments:
adapter: gridfs
Keep the URI, database and bucket in environment variables so dev/test/prod can diverge without touching YAML.
Selective adoption, not big-bang
Oro exposes several logical filesystems (private, public, attachments, and per-feature ones). Pointing only attachments at GridFS is the low-risk pattern: it isolates the blast radius, keeps public assets on a CDN-friendly adapter, and gives you a clean A/B comparison of performance under real upload volume.
Reuse the configured filesystem in custom code
Do not instantiate a GridFS adapter manually in your bundle. Inject the filesystem/filesystem manager service that Oro already built from config:
public function __construct(private Filesystem $attachmentsFilesystem) {}
public function store(UploadedFile $file): void
{
$stream = fopen($file->getRealPath(), 'rb');
try {
$this->attachmentsFilesystem->writeStream($path, $stream, ['mimetype' => $file->getMimeType()]);
} finally {
if (is_resource($stream)) {
fclose($stream);
}
}
}
This keeps you adapter-agnostic — swapping back to local disk or S3 later becomes a config change instead of a code change.
Migration pattern
Existing files stay where they are; changing the adapter does not move them. Write an idempotent console command that:
EntityManager::clear() between batches).Run it with a --dry-run flag first, and keep the old storage mounted read-only for a rollback window.
Testing
Filesystem/FilesystemInterface; you are testing your service, not GridFS.fs.files/fs.chunks collections in tearDown. Reuse the bundle's config with an env override rather than duplicating it.Operational hygiene
fs.files.filename and fs.files.uploadDate; GridFS only creates files_id/n indexes on chunks by default.fs.chunks count and total collection size in monitoring — that is your real storage gauge.mongodump includes GridFS collections, so your backup story is "back up the Mongo database," not "back up a directory."The package is a config shim, not an implementation. Its release history stopped in 2020 with zero stars and no dependents, so treat it as a reference implementation. Read it, copy the 50 lines of config/service wiring into your own bundle if needed — that gives you PHP 8 / Flysystem v2–v3 / modern mongodb driver support you will not get from the package as-is.
Version pins will bite. league/flysystem v1 GridFS adapters are incompatible with v2/v3 APIs; Oro itself has moved across those majors. Run composer why-not on each transitive dependency before you invest, and expect to pin or fork.
Driver confusion. ext-mongo (legacy) versus ext-mongodb (current) produce very different errors, often at container compile time or on first connection. php -m | grep mongo and check MongoDB\Driver\Manager availability before debugging anything else.
No transactions across file + entity. A successful GridFS write followed by a failed Doctrine flush leaves an orphaned file; a deleted entity without a matching filesystem delete leaves orphaned chunks. Two mitigations: (a) always delete through a service that does filesystem-then-entity in a try/finally with compensating deletes, and (b) schedule a reconciliation command that diffs fs.files against your file entity table and reports orphans (report before you auto-delete).
Memory and timeouts. GridFS through Flysystem is stream-based — never file_get_contents() a large file or you will hit memory_limit. Also raise upload_max_filesize, post_max_size, max_execution_time, and the web server's client_max_body_size; these failures look like generic 500s and get misattributed to GridFS.
Bucket naming is load-bearing. Changing bucket silently points at a different set of collections — your files "disappear" rather than error. Namespace buckets per environment or per application, and document the mapping.
Config caches hide your changes. Oro caches the compiled container aggressively. After touching filesystem config: cache:clear, then oro:platform:update (or your app's equivalent) so system configuration is rebuilt. Symptom of skipping this: the adapter silently stays the old one.
Connection string details. Auth against a database other than the one you are writing to requires ?authSource=admin. Without a replica set, GridFS works but you lose durability guarantees and any w:majority-style write concern.
Debugging playbook.
debug:container and debug:config for the bundle's actual service ids and resolved config — do not trust the docs.debug:router/logs for 500s during upload.fs.files directly for metadata (mimetype, original filename) — if it is missing, the Flysystem config array was not passed through.Extension points. The clean places to intervene are: (1) your own adapter factory service decorated over the bundle's, (2) a compiler pass if you need one bucket per tenant/filesystem, (3) a system configuration node if ops needs to toggle this from the admin UI, and (4) a metadata enricher that stamps tenant/owner info onto GridFS metadata at write time — doing this later requires rewriting every file.
When not to use it. GridFS is a poor CDN. If the files are predominantly public, cacheable assets, keep them on S3/object storage with a CDN in front and reserve GridFS for private attachments where you want file metadata to live next to your Mongo data.
How can I help you explore Laravel packages today?