linkorb/objectstorage
Linkorb ObjectStorage is a lightweight PHP abstraction layer for object storage, providing a consistent API to upload, retrieve, and manage files across local and cloud-backed storage systems. It simplifies integrating multiple storage backends into PHP applications.
Install the package via Composer and confirm the version resolves against your PHP/Laravel stack:
composer require linkorb/objectstorage
Before writing any application code, open the repository and read three things in this order:
src/ — find the primary ObjectStorage class (the façade you'll inject) and the concrete adapter implementations underneath it. The adapter list tells you which backends are actually supported.composer.json — check the PHP constraint and any suggest/require entries. If it targets PHP 7.x, verify it installs cleanly on PHP 8.README.md / examples — the constructor arguments for each adapter reveal what credentials and options you need.Minimal first use case — push a file and read it back:
use LinkORB\Component\ObjectStorage\ObjectStorage;
// ...instantiate the concrete adapter with your credentials...
$storage = new ObjectStorage($adapter);
$storage->putObject('reports/2024-q1.pdf', fopen($path, 'r'));
$stream = $storage->getObject('reports/2024-q1.pdf');
In Laravel, don't instantiate it inline. Register it in a service provider and drive configuration from config/filesystems.php or a dedicated config/objectstorage.php so credentials come from .env.
Bind a singleton in a service provider. Configure the adapter once and resolve the ObjectStorage instance through the container. Consumers should type-hint the façade, never the adapter.
Wrap it in a small application service. Treat ObjectStorage as infrastructure. Put your own FileUploader / DocumentStore class in front of it so controllers don't depend on a 2019-era package directly. This is your escape hatch when you later migrate to Laravel's native Storage.
Custom Flysystem driver (if the adapter maps cleanly). If the underlying API is S3-compatible or similar, consider implementing a Laravel filesystem driver that delegates to this package, so the rest of the app keeps using Storage::disk('...')->put(...). That keeps call sites idiomatic and confines the dependency to one class.
Stream, don't buffer. Most object storage adapters accept and return streams. Pass fopen() or Illuminate\Http\UploadedFile::readStream() rather than file_get_contents() so large uploads don't blow PHP memory limits.
Test with a stub adapter. Because the public surface is an adapter interface, write a small in-memory fake implementing the same methods and bind it in tests. You avoid hitting real cloud storage in CI entirely.
Background jobs for uploads/downloads. Object storage round-trips are network-bound. Push writes into queued jobs when the user doesn't need synchronous confirmation, and consider signed/temporary URLs for serving private objects instead of proxying bytes through PHP.
It's dormant. Last release was August 2019 and the project has minimal traction. Expect no upstream fixes, no security patches, and possible friction with current PHP 8 / Laravel 10+ dependency constraints. Fork it or vendor it if you rely on it.
No first-party Laravel integration. There is no service provider, facade, or config publishing. You write all the wiring yourself — budget for that up front.
Adapter feature parity is uneven. Abstractions like this typically expose a lowest-common-denominator API. Operations that feel essential (multipart upload, object metadata, presigned URLs, server-side copy, listing with pagination) may exist on one adapter and be missing or silently unsupported on another. Check the concrete adapter, not the interface, before designing around a feature.
Error semantics vary. Exception types and error codes come from whatever HTTP client the adapter wraps. Normalize failures in your wrapper service (catch adapter-specific exceptions, rethrow as your own StorageException) so calling code isn't leaking vendor details.
Credential handling. Keep keys in .env, never in the config array committed to git. If the adapter accepts a client object, inject the pre-configured client rather than letting the package build one, so you control timeouts and retry policy.
Debugging. Network/credential issues surface as opaque exceptions. Log the request (bucket, key, operation) at debug level in your wrapper, and test against a local S3-compatible service (MinIO) to isolate whether a failure is your code or the cloud endpoint.
Extension points. The intended customization seam is a custom adapter implementing the storage interface — use it for backends the package doesn't ship. Combined with the wrapper-service pattern above, that gives you a clean swap path.
Evaluate the alternative first. If your backend is S3, GCS, or Azure, Laravel's built-in Storage (Flysystem 3) is actively maintained, has a large adapter ecosystem, and needs no glue code. Only reach for linkorb/objectstorage if it targets a backend Flysystem doesn't cover or you're maintaining a legacy integration that already depends on it.
How can I help you explore Laravel packages today?