Object Store
First-class object storage for Vortos with Cloudflare R2 defaults, S3-compatible semantics, direct uploads, lifecycle cleanup, outbox promotion, and observability.
Object Store
vortos/vortos-object-store is the first-class object storage package for Vortos. It uses S3-compatible semantics so Cloudflare R2, AWS S3, and other compatible providers can share one application contract.
The package is optimized for the default enterprise upload path: the backend creates short-lived upload intent objects, browsers upload directly to object storage, and command handlers promote validated temporary files to permanent keys through an outbox.
Direct-to-cloud is the default design
Large public uploads should not stream through PHP workers. The backend issues a presigned upload URL or POST policy, then stores object keys. This keeps web workers available under heavy upload traffic.
What The Package Covers
- S3-compatible driver with Cloudflare R2 defaults.
- Typed object keys, content types, metadata, byte ranges, upload constraints, and presigned URLs.
- Direct upload lifecycle: create intent, promote temporary object, abort temporary object.
- Transactional object-store outbox for writes, deletes, copies, moves, promotions, and aborts.
- Explicit service interfaces for transactional, standalone async, and immediate provider behavior.
- Temporary upload lifecycle rule planning and application.
- Trusted server-side multipart transfers for backend-owned streams and files.
- Circuit breaker for fast-fail protection when the provider is unavailable.
- Provider exception mapping into Vortos exceptions.
- Logging, tracing, and metrics with global and section-level opt-outs.
- Testing fake for application tests.
Provider Strategy
The package exposes S3 bucket semantics intentionally. R2 is S3-compatible for object APIs, and AWS S3 remains the broadest interoperability contract in the object storage ecosystem.
The result is one Vortos API:
use Vortos\ObjectStore\Contract\ObjectStoreInterface;
$object = $objects->head('assets/invoices/inv-1001.pdf');and provider-specific configuration at the edge:
$config
->driver('s3')
->provider('r2')
->region('auto')
->bucket($_ENV['OBJECT_STORE_BUCKET']);Documentation Map
Quickstart
Install, configure, and create your first direct upload intent.
Configuration
Full config reference for client, bucket, retry, outbox, lifecycle, multipart, and observability settings.
Direct Uploads
Browser-to-R2/S3 upload flow with content type and size constraints.
Outbox Promotions
Atomic promotion from tmp keys to permanent keys inside command handlers.
Lifecycle Cleanup
Managed tmp object expiration rules with explicit commands.
Multipart
Trusted backend multipart transfers and stale upload cleanup.
Circuit Breaker
Fast-fail protection when the provider is unavailable.
Service Guarantees
The injected interface is the delivery guarantee.
use Vortos\ObjectStore\Contract\ObjectStoreInterface;
use Vortos\ObjectStore\Contract\DirectUploadManagerInterface;
use Vortos\ObjectStore\Contract\StandaloneObjectStoreInterface;
use Vortos\ObjectStore\Contract\StandaloneDirectUploadManagerInterface;
use Vortos\ObjectStore\Contract\ImmediateObjectStoreInterface;
use Vortos\ObjectStore\Contract\ImmediateDirectUploadManagerInterface;ObjectStoreInterface and DirectUploadManagerInterface are the normal business workflow path. Mutations write to the object-store outbox and require the active command transaction.
StandaloneObjectStoreInterface and StandaloneDirectUploadManagerInterface write to the outbox in their own short transaction.
ImmediateObjectStoreInterface and ImmediateDirectUploadManagerInterface call the provider directly with no outbox.
Package Registration
use Vortos\ObjectStore\DependencyInjection\ObjectStorePackage;
$packages = [
// ... other packages
new ObjectStorePackage(),
];The package is optional. Projects that do not install or register it do not get object-store services, commands, tables, lifecycle tooling, or workers.