smorken/storage
A Laravel storage helper package that streamlines saving, retrieving, and organizing files across local and cloud disks, with a clean API for uploads, file attachments, and everyday filesystem tasks in Eloquent applications.
Before writing any code, read the repo's composer.json and README.md first — this package is marked deprecated, so the two things you need to confirm up front are (a) which Laravel/PHP versions the constraints actually allow, and (b) whether a ServiceProvider and config/storage.php are auto-discovered or require manual registration. If the package predates Laravel 5.5 package auto-discovery, you'll need to add Smorken\Storage\StorageServiceProvider::class to config/app.php.
Then:
composer require smorken/storage (expect to pin a version, since an abandoned package won't get compat fixes for newer Laravel releases).php artisan vendor:publish --provider="Smorken\Storage\StorageServiceProvider" and inspect the disk defaults.Storage) and do a first round-trip: write a file, list it, read it back, delete it.The earliest useful first use case is almost always uploaded-file persistence: taking an UploadedFile from a request, pushing it to a configured disk through the package's abstraction, and recording the returned path/key against a model. Do that end-to-end before wiring anything more ambitious, because it exercises config, disk resolution, and any path-normalisation logic in one pass.
Because the package is deprecated, also do a quick feasibility check: does Laravel's native Illuminate\Support\Facades\Storage cover your use case without it? If yes, start there and treat this package only as a migration source.
Thin wrapper, not a replacement. Treat the package as an adapter over Laravel's filesystem rather than a parallel storage system. Wherever it exposes a driver/disk concept, map it onto config/filesystems.php disks so your team only has one mental model. If it introduces its own disk config keys, document the mapping in your README — this is the single biggest source of confusion when onboarding.
Constructor injection over facades in your own code. Resolve the package's service through the container and inject it into the classes that need it. That keeps your code testable and, crucially, makes it a one-line swap when you eventually migrate off the deprecated package. Wrap it behind your own interface (FileStore) if you're using it in more than a couple of places.
Storage paths as values, not strings scattered around. Whatever the package returns from a write (path, key, URL), store that verbatim on your model and always go back through the package/disk to resolve it. Never concatenate a disk root or public URL by hand — disk configs change between local, staging, and production.
Queued work is the natural home for it. If the package does anything non-trivial (image processing, remote uploads, copying between disks), push it into a job and use the package's service inside handle(). This also makes retries and failure logging sane.
Model integration, if the package ships a trait. If there's an attachable-files trait, use it only on models where the relationship is genuinely one-to-many, and add a deleting observer to clean up orphaned files. Trait-based file handling is convenient but leaks storage concerns into your domain models — keep it confined.
Testing pattern. Use Storage::fake() against the underlying disk in feature tests, and assert on the package's return values. For unit tests around your wrapper, bind a stub implementation of your own FileStore interface. This is also your safety net given the package won't get upstream fixes.
Integration tip for multi-disk setups. Explicitly pass the disk/driver on every call rather than relying on a package default. Ambient defaults are a classic "works locally, writes to the wrong bucket in prod" bug.
composer.json, add a note in your project README and a ticket to migrate to native Storage. No upstream security or compat patches are coming — don't let it silently become load-bearing infrastructure.illuminate/* constraints will block framework upgrades. Expect to either fork it or move to native filesystem APIs when you next bump Laravel. Test the upgrade in a branch before committing to a major version bump.php artisan config:cache, you'll get "works in dev, broken in prod" behaviour. Run config:cache locally (php artisan config:clear afterwards) to reproduce and catch this early.Storage::put() calls, especially on a shared disk. Verify both public and private visibility behaviour, and check storage/app ownership after any deploy pipeline change.temporaryUrl support may emit plain paths — don't assume signed URLs are handled... handling) — printing both sides of the resolution makes them obvious.null/false instead of throwing. Wrap write/delete calls and check return values explicitly; don't rely on exceptions bubbling up.How can I help you explore Laravel packages today?