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

Storage Bundle Laravel Package

swp/storage-bundle

swp/storage-bundle is a Symfony bundle that wires a configurable storage layer into your application, giving you one abstraction for reading, writing, and managing files across local and remote backends. Service-based configuration keeps storage concerns out of your application code.

View on GitHub
Deep Wiki
Context7

Getting Started

First, understand what you're installing. swp/storage-bundle is a read-only subtree split of the Superdesk Web Publisher monorepo (SuperdeskWebPublisher/SuperdeskWebPublisher, under src/SWP/Bundle/StorageBundle). It is not an independently maintained library: there are no issues, PRs, or CI in this repo. Treat it as a Composer-visible slice of the main app, not a package you adopt on its own.

Minimal steps:

  1. Do not composer require swp/storage-bundle into an arbitrary Symfony app. Pull it transitively via swp/core-bundle (or the superdesk/web-publisher application skeleton) so the swp/* versions stay in lockstep. Mixing a lone swp/storage-bundle with an unrelated Symfony version is the fastest way to a broken container.
  2. Check the baseline. Last tagged release is 2018-06-08; expect Symfony 3.4/4.x-era service definitions, Flysystem 1.x (League\Flysystem\Filesystem, AdapterInterface), and PHP 7.1–7.3 idioms. Confirm your app's PHP/Symfony before wiring anything.
  3. Register the bundle the usual way (AppKernel::registerBundles() or config/bundles.php depending on your Symfony generation).
  4. Read the config tree before the docs. The authoritative reference is DependencyInjection/Configuration.php in the bundle — that file defines every swp_storage key. Pair it with Resources/config/services.yml to see which service IDs the config drives (the filesystem service, adapter, and any namer/strategy services).
  5. Configure your first filesystem under swp_storage:, typically selecting a local adapter and a root directory (e.g. %kernel.project_dir%/var/storage or web/uploads), with an S3/other adapter reserved for production.
  6. First use case: handle a single image upload — take a Symfony UploadedFile, write it through the bundle's Flysystem-backed filesystem service, persist only the relative path on your entity, and render it via a route or asset base URL.

Where to look first, in order: DependencyInjection/Configuration.php → Resources/config/services.yml → the storage/filesystem classes under the bundle's Storage/ (or equivalent) namespace → Tests/ for the intended usage shape.

Implementation Patterns

Inject the filesystem, never touch the disk directly. The bundle's value is that it hands you a configured League\Flysystem\FilesystemInterface (aliased in the container). Type-hint that interface in your services and use write, writeStream, read, readStream, has, delete, listContents. This keeps local/S3 swap-out a config change rather than a code change.

public function __construct(private FilesystemInterface $filesystem) {}

public function store(UploadedFile $file, string $dir): string
{
    $path = sprintf('%s/%s.%s', $dir, bin2hex(random_bytes(8)), $file->guessExtension());
    $this->filesystem->writeStream($path, fopen($file->getPathname(), 'rb'));
    return $path; // persist this relative path only
}

Separate storage path from public URL. Persist relative paths (articles/images/ab12cd.jpg) in Doctrine. Resolve to a URL at render time through an asset base URL, CDN prefix, or a streaming controller for private files. Never store absolute filesystem paths — they break the moment the adapter changes.

Multiple filesystems per environment. Define a local adapter for dev/test and an object-store adapter for prod, both behind the same interface. Inject an alias per consumer (public media vs. private documents) so a misconfiguration can't leak private files into the public bucket.

Stream, don't buffer. News-media workloads mean large images and PDFs. Use writeStream/readStream and getSize/getMimetype rather than file_get_contents through the adapter. Add a cached adapter (Flysystem's CachedAdapter) if you call listContents in listing screens.

Deterministic rendition naming. If you generate thumbnails, derive names like <path>/<name>_<width>x<height>.<ext> so lookups are pure functions of the original path, and deletion can enumerate derived files by prefix.

Upload validation belongs before storage. Validate mime type, extension, and size in a Symfony form/constraint, then hand the stream to the filesystem. The bundle is a storage layer, not a validator; don't expect it to reject a .php renamed to .jpg.

Wrap it in your own narrow interface. Define App\Storage\StorageInterface with store(), delete(), url() and adapt the bundle's filesystem inside. This is the single most valuable pattern here: it isolates your domain from a 2018 subtree split and makes a future Flysystem 3 migration a one-class change.

Testing. Point the adapter at var/tests/storage (or an in-memory adapter) in config/packages/test/, truncate between tests, and assert on paths rather than bytes. If the bundle ships fixtures/factory services, reuse them instead of hand-rolling uploads.

Gotchas and Tips

  • Subtree split etiquette. Never open a PR or issue here; upstream changes belong in the SuperdeskWebPublisher/SuperdeskWebPublisher monorepo. Any local patch you make will be silently overwritten on the next split sync — fork the monorepo or vendor-patch instead.
  • AGPL-3.0 is a real constraint. Strong copyleft with a network clause: offering the software as a service obligates you to publish source. For a commercial product this needs legal review or an alternative — do not treat it as MIT-adjacent because it's "just a storage bundle."
  • Staleness is the headline risk. Last release 2018, zero dependents, zero stars. On Symfony 5/6 you will hit container compilation errors: removed Definition methods, changed autowiring aliases, FileLocator::locate() signature drift, and Flysystem 1.x vs 3.x API breakage (AdapterInterface was split into FilesystemAdapter/FilesystemOperator). Budget for a rewrite of the wiring, not a tweak.
  • Config keys fail loudly but unhelpfully. An adapter name string that doesn't match an available adapter service typically surfaces as a ServiceNotFoundException deep in a compiler pass. Run bin/console debug:container swp_storage and debug:container --tag=<storage tag> to confirm what was actually registered; check the compiled container in var/cache/dev when in doubt.
  • Path normalization bites. Flysystem strips leading slashes and rejects .. segments. Don't pass absolute paths or Windows-style separators. For the local adapter, set the root as an absolute path (e.g. %kernel.project_dir%/var/storage) — relative roots resolve against the working directory and "work" in CLI but fail under PHP-FPM.
  • Permissions and SELinux. var/ or web/uploads must be writable by the web user; containerized setups frequently need an explicit volume plus a matching UID. A silent write() returning false is almost always permissions, not code.
  • Orphan cleanup. Deleting an entity doesn't delete files. Add a Doctrine postRemove listener or a scheduled command that reconciles DB paths against listContents, including renditions.
  • Extension points to prefer over patching: a custom adapter registered as a service and referenced by the config adapter name; a custom namer/strategy service where the bundle exposes one; and event subscribers on post-persist to sync metadata. These survive subtree-split updates; edits inside the bundle don't.
  • Pin the family, not the package. If you must use it, constrain swp/* together to the same commit/version and commit composer.lock. A lone version bump on swp/storage-bundle will desync from swp/core-bundle and fail at runtime.
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
cgv/localized-resource