sylius/storage
Sylius Storage offers a lightweight, adapter-based abstraction for file storage in Sylius and PHP applications. It separates persistence from domain logic, supports interchangeable backends such as local filesystems, and keeps file handling testable and framework-friendly.
What the package actually is. sylius/storage is not a Laravel package. It is a read-only subtree split of the Sylius e-commerce monorepo's data storage component: a thin, framework-agnostic PHP abstraction (a StorageInterface plus a filesystem-backed implementation) originally used to persist uploaded assets such as product, taxon, and avatar images. There is no service provider, no facade, no config file, no illuminate/* constraint, and no Laravel-specific affordances. Its only real consumers are Sylius applications and Sylius-adjacent bundles.
Architecture fit. Poor for a Laravel codebase. Laravel already ships a first-class filesystem abstraction (Illuminate\Filesystem\FilesystemManager over Flysystem), plus UploadedFile, validation rules, and queue-friendly handling. sylius/storage operates at a lower level and predates the Flysystem-based approach Sylius itself migrated to, so adopting it means introducing a parallel storage abstraction alongside the idiomatic one. Two competing abstractions for the same concern is an architectural smell that will produce inconsistent disk configuration, duplicate path conventions, and split test coverage.
Integration feasibility. Technically possible but pointless. The component is small (single-digit class count), PSR-4 autoloaded, MIT licensed, and has essentially no transitive dependency surface beyond Symfony's Filesystem (and possibly a PSR container hint). A developer could write an adapter in hours. The problem is that "possible" is not "valuable": every behaviour it offers is a subset of what Storage::disk()->put() already provides, with the added cost of a second dependency on Symfony components inside a Laravel app.
Technical risk. High, almost entirely non-technical in origin:
| Risk | Severity | Notes |
|---|---|---|
| Archived / read-only repo | Critical | No bug fixes, no PHP version bumps, no security response. The code is frozen at whatever PHP era it was split from. |
| PHP/framework drift | High | Old constraint sets will eventually conflict with Laravel's required PHP range or with modern Symfony components pulled in transitively. |
| Zero dependents | High | 0 dependents and 6 stars confirms no ecosystem validation; nobody is exercising this code in production outside Sylius itself. |
| Ambiguous deprecation status | Medium | The [READ-ONLY] marker and the package's disappearance from Sylius' current dependency graph imply it has been superseded, but there is no explicit deprecation notice in the repository to pin the successor. |
| Security posture | Medium | File storage code carries path-traversal, MIME-sniffing, and overwrite semantics; an unmaintained implementation offers no disclosure channel. |
| Opportunity score | — | 0.03 overall against a 18.59 opportunity signal is a strong "cheap to build, no reason to consume" shape. |
Key questions to resolve before any decision.
sylius/image-processor, or the LiipImagine stack), and does the replacement have a maintained, Laravel-compatible equivalent?Verdict. Treat this as reference material, not a dependency. Recommendation: do not adopt; re-implement the interface contract on top of Laravel's native filesystem layer if a migration path from Sylius is required. Value is in reading ~15 minutes of its interface semantics, not in composer require.
Stack fit. Effectively zero. A Laravel service provider would need to be authored from scratch to register the interface, bind a concrete implementation, and expose configuration for base path and disk. That provider, not the package, becomes the thing you maintain. Meanwhile Laravel's config/filesystems.php already expresses disks, drivers, visibility, and per-environment roots — introducing a second configuration surface for the same concept multiplies operational confusion.
Recommended migration path (Sylius → Laravel). Rather than porting the package, port the contract:
ImageStore) with those operations expressed in your domain vocabulary, not Sylius'. Keep it narrow — this is the seam that lets you swap implementations later.Storage::disk($disk), using put, exists, get/response, delete, and url. Path generation, filename sanitisation, and content-hash naming belong in this adapter, not in callers.Compatibility considerations.
composer.json constraint against your target PHP. An unmaintained package pinned to an older minor will force a config.platform override or a composer conflict — both are unacceptable long-term.Filesystem into a Laravel app for a wrapper you could write in an afternoon is a net-negative dependency trade.url()/Storage::url() plus CDN config should own this. Any environment-dependent string baked into storage keys is a bug waiting for the first staging deploy.Sequencing.
Explicit non-goal. Do not install sylius/storage "temporarily" to shorten the spike. An archived dependency acquired for convenience has a habit of outliving the sprint that justified it.
Maintenance. Total, non-negotiable, and entirely on your team. The repository is archived and read-only, which in practice means: no security patches, no PHP compatibility work, no bug triage, no upstream to rebase against. If the code is adopted and later needs a one-line fix, you fork — and a fork of an archived package is a permanent, unowned liability that shows up in every future upgrade review. The only sane maintenance posture is zero adoption.
Support. There is no support channel. Six stars and zero dependents mean the effective user community is you. Stack Overflow and issue-search will return nothing useful. Institutional knowledge lives in Sylius' own documentation, not in this repository, and that documentation describes a version of the component that Sylius itself has moved past. Any onboarding doc you write becomes the sole source of truth — budget for that.
Scaling. The component's scaling characteristics are inherited entirely from the underlying filesystem, and it makes no promises about concurrency. Concerns a TPM must flag:
The Laravel-native path avoids all of this: Storage::disk('s3') scales horizontally by default and puts CDN and lifecycle policy one config change away.
Failure modes. In rough order of likelihood and blast radius:
| Failure mode | Impact | Mitigation if adopted (not recommended) |
|---|---|---|
| Silent write failure ignored by caller | Missing product images, 200 OK responses | Assert on every write, alert on failure rate |
| Path traversal via unsanitised filename | Arbitrary file write/read | Strict key generation, reject caller-supplied paths |
| Local disk fills or node is replaced | Permanent asset loss | Object storage with versioning; never rely on node-local state |
| Orphaned files after DB rollback | Storage bloat and drift between DB and disk | Transactional outbox or reconciliation job |
| PHP upgrade blocks the pinned constraint | Upgrade freeze across the whole app | Fork and patch — a recurring tax |
| No security disclosure path | Undefined dwell time on a future CVE | Fork, monitor independently, accept risk |
Ramp-up. Cheap in isolation, expensive in context. The component itself is a few hundred lines and readable in an hour. The real cost is the anti-pattern: engineers must learn both the legacy abstraction and the native Laravel one, and must remember which applies where. New hires arriving from a Laravel background will reasonably reach for Storage:: and produce inconsistent results. Every code review becomes a policy discussion. That coordination overhead persists for as long as the package remains installed, long after the migration that justified it is complete.
Bottom line for the roadmap. No integration work should be scheduled against sylius/storage. The scoring shape — a negligible consumption score against a healthy opportunity signal, zero dependents, archived status — is a textbook "learn from it, don't depend on it" profile. If a Sylius migration is genuinely in scope, allocate the sprint to porting the storage contract onto Laravel's native filesystem layer, and treat this repository as fifteen minutes of design input rather than a dependency in composer.json.
How can I help you explore Laravel packages today?