Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Esdk Obs Php Laravel Package

obs/esdk-obs-php

PHP SDK for Huawei Cloud OBS (Object Storage Service). Provides client APIs for buckets, objects, multipart uploads, ACLs, lifecycle rules, and signed URLs, making it easy to integrate scalable cloud storage into Laravel or plain PHP applications. Includes examples and configuration support.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the official Huawei Cloud OBS SDK:

composer require obs/esdk-obs-php

Credentials come from the Huawei Cloud console (IAM → My Credentials → Access Keys), or preferably from environment variables / a secrets manager. The minimum viable client:

use Obs\ObsClient;

$client = new ObsClient([
    'key'      => config('filesystems.disks.obs.key'),
    'secret'   => config('filesystems.disks.obs.secret'),
    'endpoint' => 'https://obs.cn-north-4.myhuaweicloud.com', // must match bucket region
]);

$client->putObject([
    'Bucket' => 'my-bucket',
    'Key'    => 'avatars/user-1.png',
    'Body'   => file_get_contents($path),
]);

First use case to sanity-check: upload a file, then getObject it back and read ->getBody(). Second: generate a presigned GET URL with createSignedUrl and confirm it downloads in a browser. If those two work, credentials, endpoint, region, and bucket policy are all correct — which is 90% of setup failures.

Look first at the examples/ directory in the repo (it ships a full set of runnable samples) and the ObsClient class method list — it mirrors the OBS REST API 1:1 (putObject, getObject, listObjects, createBucket, deleteObject, copyObject, createSignedUrl, etc.).

Implementation Patterns

Bind a singleton in a Laravel service provider. The client wraps a Guzzle handler and is safe to reuse across requests; constructing it per call wastes TLS handshakes.

$this->app->singleton(ObsClient::class, fn () => new ObsClient([
    'key'      => config('filesystems.disks.obs.key'),
    'secret'   => config('filesystems.disks.obs.secret'),
    'endpoint' => config('filesystems.disks.obs.endpoint'),
]));

Wrap it in a small storage service, not raw calls. Controller code should call $storage->put($key, $contents, $mime) so you can swap OBS for S3 locally and centralize key generation, prefixing, and error translation.

Custom Laravel filesystem driver is the highest-leverage integration if you use Storage::disk('obs'), Spatie Media Library, or ->store() calls. There is no first-party adapter in this package; either write a League\Flysystem\Adapter implementation around putObject/getObject/deleteObject, or adopt a community filesystem bridge. Once wired, existing code treats OBS like any other disk.

Presigned URLs for private buckets. Keep buckets private and hand out short-lived URLs — this is the standard pattern for user uploads/downloads:

$url = $client->createSignedUrl([
    'Method'  => 'PUT',            // or 'GET' for downloads
    'Bucket'  => 'my-bucket',
    'Key'     => "uploads/{$uuid}",
    'Expires' => 900,              // seconds
    'Headers' => ['Content-Type' => 'image/png'],
]);

Stream large files, don't buffer them. For uploads over a few MB use Body as a stream resource (fopen($path, 'r')) so Guzzle chunks it, and for very large objects use the multipart helpers (initiateMultipartUpload / uploadPart / completeMultipartUpload) or the SDK's uploadFile convenience method so you get parallel part uploads and resumability.

Queue non-critical writes. Uploads, deletions, and thumbnailing are ideal job payloads. Store the OBS key on the model, dispatch a job, and use the queue's retry/backoff for transient 5xx or throttling responses.

Prefix-based organization. Use keys like {tenant}/{model}/{uuid}-{filename} — OBS is a flat keyspace, so prefixes are your "folders" and make listObjects with Prefix + MaxKeys + Marker cheap and predictable for cleanup jobs and audits.

Gotchas and Tips

  • Endpoint must include the region and scheme. obs.cn-north-4.myhuaweicloud.com will fail for a bucket in another region; use the region-specific endpoint, not the generic one.
  • Responses are model objects, not arrays. $resp['HttpStatusCode'], $resp['ObjectURL'], and $resp->getBody() are the accessors — the body is a Guzzle stream. Read once with (string) $resp['Body'] or getContents(), then close it.
  • Errors throw ObsException, not return false. Always wrap in try/catch and branch on $e->getExceptionCode() (e.g. NoSuchKey, AccessDenied, SignatureDoesNotMatch) rather than parsing messages.
  • Clock skew breaks signing. SignatureDoesNotMatch with correct keys almost always means server time is off — sync NTP on the app host.
  • ACLs vs bucket policy. New buckets default to private. If static assets 403 in the browser, you need either ACL => 'public-read' on the object (or bucket policy) or a CDN in front. Prefer CDN + private bucket for production.
  • Autoload conflict. Older releases ship their own autoloader.php and use a non-PSR-4 layout. If classes aren't found, check composer.json's classmap/files autoload or require the SDK autoloader once in a bootstrap file. Composer 2's stricter PSR-4 warnings can be loud here.
  • Content-Type isn't inferred reliably. Set ContentType explicitly (or via Mimetypes in the SDK) or browsers will download instead of render.
  • listObjects is paginated. Loop on IsTruncated with NextMarker; a single call returns max 1000 keys. Deleting "everything under a prefix" needs the same loop.
  • Turn on debug logging temporarily via the debug/log_path config options when signatures fail — the request/response dumps show the exact canonical request OBS rejected.
  • Extension points: subclass ObsClient or inject a custom Guzzle handler stack to add retries, request IDs for tracing, or metrics middleware. The SDK exposes its underlying HTTP client config, which is where you add timeouts and connection pooling for high-throughput workloads.
  • Pin the version. Last release was 2024-10 and the project is low-velocity (58 stars); lock the Composer constraint and read the changelog before upgrading — there is no Laravel ecosystem pressure forcing regular updates.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource