1tomany/storage-bundle
A Symfony bundle for uploading files to remote storage services like Amazon S3, Cloudflare R2, Google Cloud Storage, and Azure Blob Storage, plus a mock client for testing integrations without a network connection.
Storage facade + Flysystem drivers for S3 and R2, plus Storage::fake() for tests). The package only earns its place if it beats that baseline on a specific axis.onetomany_storage.client config key and a tagged ClientInterface, so switching from S3 to an S3-compatible provider (Cloudflare R2) is configuration, not code. This supports a "don't get locked into one object store" positioning in our architecture docs — useful when procurement or finance wants leverage on egress costs.custom_url setting rewrites returned object URLs to a CloudFront or public R2 domain (https://files.app-cdn.com/users/10/files/avatar.png). This directly supports product decisions around image/asset delivery performance and CDN cost control without touching application code.UploadActionInterface / DownloadActionInterface / DeleteActionInterface seam, which keeps storage concerns out of domain code and makes a future "bring your own bucket" enterprise ask less expensive.mock_client removes network dependency from tests. In a Laravel shop this is a feature-parity decision, not a differentiator — we should benchmark it against Storage::fake() before crediting it in a build-vs-buy comparison.Consider it when:
UploadActionInterface) rather than a disk/facade model — the README's rationale (clear intent in constructor signatures, pre/post-processing hooks, easier mocking of one method) is legitimate and worth crediting.Look elsewhere when (this will be most cases):
Storage disks, the S3/R2 drivers, Storage::fake(), and temporaryUrl(). We get more capability, zero glue, and first-party maintenance.composer.json that we would have to manage forever.UploadRequest takes a path/format/key, not Laravel's UploadedFile — an adapter is required and is ours to write and test.Recommendation for the decision log: do not adopt as a dependency of record. Run a timeboxed one-to-two week spike behind a StorageGateway interface we own; if the spike fails to beat the native Storage facade on multi-provider switching or CDN URL handling, close the evaluation and keep Flysystem.
To executives (one paragraph): This is a small, MIT-licensed library that standardizes uploading, downloading, and deleting files across cloud storage providers, with a built-in mock for testing and a simple setting to serve files from our own CDN domain. The license is free and the integration cost is low, but its adoption signals are essentially zero — no known users, one maintainer — and our Laravel stack already provides comparable capability out of the box. Recommendation: fund a two-week evaluation, not an adoption. The upside is a cheap option to move between storage vendors and control CDN delivery; the downside is glue code we own and a dependency we may have to fork. Treat it as a low-cost hedge, not a strategic platform bet, and do not let it become a single point of failure on the media path.
To engineering (the honest version): The design is sound — ClientInterface with tagged, config-keyed clients; three action interfaces (Upload/Download/Delete) that give us one-method seams and clean test doubles; a mock_client for offline tests; and custom_url for CDN rewriting. Two caveats you should price in: it's a Symfony bundle, so Laravel means a service provider, config bridging, and an adapter between Symfony's request objects and Illuminate\Http\UploadedFile; and it has no facade, no temporaryUrl(), no presigned or chunked uploads, and the GCS/Azure claims in the README are undocumented. The Symfony 8 dependency in v3.0.1 is a real conflict risk against our pinned components. What we'd build either way: a StorageGateway abstraction we own, with this package as one swappable implementation behind it — so the eval is decoupled from the adoption decision, and backing out costs one class.
How can I help you explore Laravel packages today?