hpcloud/hpcloud-php
HPCloud PHP is a PHP SDK for integrating applications with HP Cloud services. It provides authentication and clients for identity, object storage, and compute APIs, helping developers manage cloud resources and build integrations with less boilerplate.
Minimal steps
composer require hpcloud/php-openstack:^1.3 (the HP Helion / HPCloud PHP SDK). Pin to ^1.3 — releases before 1.3.0 have transport bugs on Windows and on current Linux/macOS builds (see Gotchas).config/hpcloud.php or equivalent) and drive it entirely from .env: HPCLOUD_AUTH_URL, HPCLOUD_USERNAME, HPCLOUD_PASSWORD or HPCLOUD_ACCESS_KEY/HPCLOUD_SECRET_KEY, HPCLOUD_TENANT_ID, HPCLOUD_REGION.Where to look first
Container / Object / StreamWrapper equivalents) — this is what you will actually use day to day.transport.debug — this is where 1.3.0 fixed the most bugs.First use case
The 80% case is: authenticate once, take a container, upload a user-supplied file to it, store the returned object name/URL on your Eloquent model, and serve it back either via a temporary URL or through a CDN-enabled container.
$identity = $app->make(IdentityService::class);
$storage = $identity->objectStoreService('cloudFiles', config('hpcloud.region'));
$container = $storage->getContainer(config('hpcloud.container'));
$object = $container->createObject('uploads/' . $uuid, fopen($path, 'r'));
Bind once, reuse everywhere
Wrap the SDK in a small ObjectStorage application service and bind it as a singleton. Laravel resolves it lazily; the identity handshake and catalog fetch happen on first use. Pass that abstraction into controllers, jobs and Blade-facing helpers so the SDK never leaks into your domain code — this also makes it trivial to swap in a Storage disk adapter later.
Token lifecycle
Tokens from this SDK expire. Cache the serialized token in Laravel's cache with a TTL shorter than the issued lifetime, and re-authenticate on a 401. Don't re-run identity on every getContainer() call — it's the single biggest source of latency in naive integrations.
File uploads
fopen($path, 'r') rather than file_get_contents(). The SDK's cURL transport will stream it, and you avoid loading 200 MB into PHP memory.Storage::disk('hpcloud') via a custom filesystem driver if you want Laravel's put/get/url API — the SDK's object model maps cleanly onto League\Flysystem's adapter contract.CDN
Enable CDN on the container you serve public assets from, then store only the container-relative object path on your model and resolve the CDN URL at render time. Keep CDN enable/disable in an artisan command rather than in request handlers — it is an infrastructure operation, not a per-request one. Note the 1.3.0 docs refresh around CDN and access/secret keys for HP Helion OpenStack / Public Cloud; the auth shape differs between those two deployments, so verify tenant and region resolution against the catalog rather than hardcoding endpoints.
Transport configuration
Let the config decide between cURL and the PHP Stream transport. Use cURL on any normal LAMP/CI environment; keep the stream transport as the fallback for hosts that disable the cURL extension. transport.debug (fixed in 1.3.0) is now honoured by both layers — wire it to config('app.debug') so you get request/response detail locally but nothing in production.
Proxy-aware deployments
If you sit behind an egress proxy, the content-length handling fixed in 1.3.0 matters — set Content-Length explicitly only when you know the payload size, and let the transport compute it for streamed bodies.
Testing
Mock at your own ObjectStorage abstraction boundary rather than the SDK. For integration tests, stand up a fake HTTP endpoint and point HPCLOUD_AUTH_URL at it; the SDK talks plain HTTP so this works without any special package.
DBaaS is gone in 1.3.0 — this is the one breaking change. The database service was a private beta against a now-deprecated API. If any code or config in your app references the DBaaS service, it will fatal on the 1.3.0 upgrade. Grep for the service class and remove the config block before bumping. There is no replacement in this package; use your cloud provider's database service directly, or a managed MySQL/Postgres add-on.
Upgrade is effectively mandatory for Windows and modern Linux/macOS. 1.3.0 fixes a cURL transport failure that hits newer OS/OpenSSL combinations (#3), stops calling posix_geteuid unconditionally on Windows (#15), and stops assuming the temp directory is /tmp (#13). Anything below 1.3.0 is a coin flip on Windows CI and Docker images with a custom sys_temp_dir. If you set TMPDIR, verify it still resolves — the SDK now respects the configured temp path.
transport.debug was silently ignored by the PHP Stream layer until 1.3.0 (#14). If you previously "enabled debug" and got nothing, that was the bug. But be deliberate: once it works, it logs full requests. Scrub auth headers before those logs hit a shared channel.
Content-Length + cURL + proxies (#13) — the fix is best-effort. If you're behind a proxy and see truncated or hung uploads, try omitting the explicit content length and letting the transport infer it.
Auth key documentation changed for a reason. HP Helion OpenStack and HP Helion Public Cloud use different access/secret key semantics. Don't copy credentials between them; validate that the service catalog actually contains a cloudFiles endpoint for the region you asked for, and fail loudly at boot if it doesn't. A missing catalog entry surfaces later as a confusing null container.
Temp directory assumptions. Large streamed uploads spool to disk. On constrained containers, point the SDK at a writable path with adequate space and monitor it — a full temp volume manifests as a transport-level error, not an obvious "disk full".
Extension points worth knowing. The transport interface is the cleanest place to inject instrumentation — subclass it to add timing metrics or to route through a corporate HTTP client. Service classes can be extended for project-specific helpers (e.g. createObjectFromModel()). Guzzle middleware hooks in only if you've replaced the underlying HTTP client; the shipped transports do not expose that seam.
Region/container drift between environments. Keep container names and regions in config, never in code. A staging job pointed at the production container is a quiet data-loss vector with this SDK because there is no dry-run mode.
How can I help you explore Laravel packages today?