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

Flysystem Laravel Package

graham-campbell/flysystem

Laravel Flysystem is a Flysystem bridge for Laravel by Graham Campbell, built on Laravel Manager. It provides a unified filesystem manager with support for local, S3, Dropbox, and other storage adapters, requiring PHP 7.4-8.1 and Laravel 8.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

What this package is. graham-campbell/flysystem is a thin Laravel service-provider/manager wrapper around league/flysystem v1.x. It registers a flysystem container binding, exposes a Flysystem facade, adds a connection()/setDefaultConnection() manager API (via graham-campbell/laravel-manager), and ships a publishable config/flysystem.php with per-driver connection stubs plus an optional cache layer (Illuminate or adapter-backed).

Architecture fit — this is the central finding. Laravel has shipped a first-party Flysystem integration since 5.0: the Storage facade and Illuminate\Filesystem\FilesystemManager already provide a manager, named disks, disk() switching, and a default-disk concept. This package materially duplicates that surface. The functional delta versus native Laravel is narrow:

  • Extra third-party adapters not covered natively (Azure Blob, Dropbox, Google Cloud Storage, GridFS, WebDAV, ZipArchive).
  • A two-tier cache abstraction (Illuminate cache store vs league/flysystem-cached-adapter).
  • A slightly different manager API (connection() vs disk()), which is not a benefit — it is a second vocabulary for the same concept.

For any greenfield or Laravel 8+ codebase, adopting this package means adding a competing filesystem abstraction alongside Storage, with no meaningful capability gain unless a specific non-native adapter is required.

Integration feasibility. Mechanically simple: composer require graham-campbell/flysystem:^8.0, publish config, optionally alias the facade. Auto-discovery handles the provider. No schema changes, no middleware, no queue/worker implications. The only real friction is dependency fan-out — each adapter pulls its own transitive tree (league/flysystem-aws-s3-v3 ^1.0, spatie/flysystem-dropbox ^1.0, superbalist/flysystem-google-storage ^7.2, alcaeus/mongo-php-adapter ^1.1 for GridFS, etc.). GridFS and Azure in particular drag in heavy, aging SDKs.

Technical risk — high, and concentrated in version ceiling. The package is pinned to a specific, closing window:

  • v8.0 requires PHP 7.4–8.1 and Laravel 8 only. Laravel 9, 10, and 11 are unsupported — the compatibility matrix explicitly terminates at L8.
  • The entire adapter ecosystem it depends on is Flysystem 1.x, which is end-of-life. Laravel 9+ moved to Flysystem 3, whose API is not backward compatible (FilesystemInterface was removed/reshaped, adapters rewritten). This is not a bump-the-constraint migration; it is a rewrite of every call site.
  • Zero dependents and a single maintainer indicate no ecosystem pressure to keep this alive; there is no community forcing function for an L9+/Flysystem 3 port.
  • Version-pinning is brittle by design: the README explicitly warns to diff the published config/flysystem.php against the package's config between releases, meaning config drift is a known, recurring operational hazard.

Key questions to resolve before any commitment.

  1. Which specific driver is the actual requirement? If it is S3, local, FTP, or SFTP, native Storage covers it and this package should be rejected outright.
  2. What is the organization's Laravel upgrade horizon? If L9+ is within 12 months, this package is a guaranteed forced-removal project — the migration cost is simply deferred, plus interest.
  3. Does the team already use Storage anywhere in the codebase? If yes, we would run two filesystem abstractions concurrently, doubling the mental model and the test surface.
  4. Is the Filesystem 1.x EOL acceptable for the data path that stores/retrieves user or regulated content? Security patching for league/flysystem v1 has effectively stopped.
  5. Does the flysystem container binding collide with anything? Laravel's container uses filesystem/filesystem.disk — the flysystem key is distinct, so collision risk is low, but confirm no internal packages resolve that key.

Integration Approach

Stack fit — conditionally acceptable, narrowly scoped. There is exactly one defensible adoption pattern: a Laravel 8 application that needs a driver Laravel does not ship natively (Azure Blob, Dropbox, Google Cloud Storage, GridFS, WebDAV, Zip) and cannot justify writing a custom FilesystemAdapter. Even then, I would first evaluate whether a modern, Flysystem 3-compatible driver package exists for that backend — that path avoids the L8 ceiling entirely. Outside that narrow case, the recommendation is reject and standardize on native Storage.

Recommended sequencing (if we proceed).

  1. Spike, timeboxed to 2–3 days. Install into a throwaway L8 branch, validate the one required driver end-to-end (write, read, list, delete, visibility), and confirm the adapter's transitive dependencies install cleanly and pass a security scan (composer audit).
  2. Freeze the decision gate. Confirm in writing that the app stays on Laravel 8 for the planning horizon. If that cannot be guaranteed, stop here.
  3. Isolate behind an interface. Do not let Flysystem:: facade calls leak into controllers, jobs, or domain services. Define a small internal port (e.g., ObjectStore with put/get/delete/url/exists) and implement it once with this package. This is the single highest-leverage decision in the whole engagement: it converts a package swap into a single-class change later.
  4. Configure explicitly, not by default. Publish config, set default deliberately, and keep local for anything that touches the request lifecycle. Add the config file to code review ownership so README-mandated diffs between releases are actually caught.
  5. Backfill migration last. Move existing Storage call sites onto the new port only if the driver genuinely must serve them; otherwise leave Storage untouched for local/S3/SFTP and let this package cover the single exotic backend. Two abstractions with a hard, documented boundary is manageable; two abstractions with overlapping scope is not.

Migration path off the package. Because the interface layer in step 3 is the only call site set, the exit is: implement ObjectStore a second time against Flysystem 3 (native Storage when Laravel 9+'s adapter story covers the backend; a modern driver package otherwise), swap the container binding, run the port's contract tests, delete the dependency. Budget roughly 1–2 engineer-weeks if step 3 is honored, 4–6 weeks if facade calls leak into application code — that delta is the entire argument for step 3.

Compatibility guardrails. Pin graham-campbell/flysystem exactly (8.0.x), not ^8.0, and commit composer.lock. Add a CI job that fails on composer update attempts touching this subtree. Explicitly forbid PHP 8.2+ images for this app, since the package declares 8.1 as its ceiling and no patch will raise it.

Operational Impact

Maintenance. Low day-to-day, but with a hard expiry date. The code surface is small and inert; there is nothing to tune. The recurring cost is tracking: config diffs between releases (which the README mandates) and a quarterly re-evaluation of the Flysystem 1.x EOL posture. Realistically, the only maintenance event that matters is the eventual forced removal, and its cost is set entirely by how well the abstraction boundary was enforced. The package itself receives minimal upstream activity — recent releases are version-ceiling adjustments (add L8, drop L5, drop PHP < 7.4), not feature work.

Support. Single-maintainer, MIT-licensed OSS with no vendor SLA. There is a Tidelift commercial subscription path, which is the one lever available if enterprise support is a procurement requirement — worth pricing if the driver is on a revenue path, though note Tidelift guarantees maintenance, not a Laravel 9 port. Security triage routes to [email protected], which is a reasonable process but not a response-time commitment. Internal ownership must be assigned by name; there is no external party to escalate to.

Scaling. Adequately horizontal — each PHP process resolves connections from config, and the manager caches the resolved connection per request. The scaling concerns are all backend-side and shared with native Laravel: S3/Azure/GCS throughput and per-object request cost, SFTP connection limits (a real ceiling under concurrency — SFTP adapters do not pool well), and GridFS performance under load. The package's cache layer deserves scrutiny at scale: adapter-level caching can serve stale listings after writes from other nodes, and Illuminate-cache-backed caching introduces a shared cache dependency on the read path — a cache outage becomes a filesystem outage. Prefer no cache for correctness-critical reads; if caching is enabled, define and test the invalidation story explicitly.

Failure modes to design for.

  • Silent config drift after a package upgrade (README-flagged) — mitigations: pin the version, review the config in PRs, and assert critical connection keys in a startup test.
  • Credential absence — the AWS adapter was made credential-optional in v4.1, so misconfiguration can surface as a runtime failure deep in a request rather than at boot. Add a health-check command that performs a cheap exists/list against each configured connection and run it post-deploy.
  • Transitive dependency rot — GridFS (alcaeus/mongo-php-adapter) and Azure (league/flysystem-azure-blob-storage) pull aging SDKs; a transitive security advisory can block a release with no upstream fix available. Monitor composer audit in CI and pre-agree a fallback (native adapter or direct SDK usage).
  • PHP/Laravel upgrade wall — the definitive failure mode. Any attempt to move to Laravel 9+ breaks at composer update. This should be captured as a known dependency-blocking item on the platform upgrade roadmap on day one, not discovered during the upgrade.
  • Partial writes / consistency — object stores are eventually consistent for listings; do not build logic that writes then immediately lists to verify presence.

Ramp-up. Low for any engineer familiar with Laravel, because the underlying Filesystem API is the standard Flysystem v1 interface and the README's examples are copy-pasteable. The genuine ramp cost is conceptual: new hires will reasonably ask why the codebase has both Storage::disk() and Flysystem::connection() doing the same job. That question has no good answer, which is itself a signal. Mitigate with a one-page ADR recording the decision, the specific driver justification, the L8 pin, and the exit criteria — and link it from the interface's docblock. Onboarding then costs minutes instead of a recurring architectural debate.

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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource