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

Laravel Qcloud Federation Token Laravel Package

overtrue/laravel-qcloud-federation-token

A Laravel package for generating Tencent Cloud federation tokens and temporary credentials. It wraps QCloud STS so you can securely issue scoped, expiring keys for COS uploads and other cloud services, with simple configuration and familiar Laravel integration.

View on GitHub
Deep Wiki
Context7

Getting Started

This release (v5.0.1) is a compatibility hardening release, not a feature release. The practical upshot for day-to-day work: the package now supports PHP 8.3, 8.4 and 8.5 cleanly, so the first thing to do is align your composer.json platform constraint and re-run your suite.

Minimal steps:

  1. composer require <vendor>/<package>:^5.0 (or composer update <vendor>/<package> if already on 5.x).
  2. Confirm your runtime: php -v should be 8.3+. If you develop on 8.4/8.5 but deploy to 8.3, set config.platform.php in composer.json so dependency resolution matches production.
  3. Run the package's own compatibility gate against your environment before wiring anything up:
composer check-runtime-compatibility
composer test
composer check-style
  1. Look first at the Statement class. It is the object you will touch most, and it is deliberately dual-purpose: it implements ArrayAccess (so a result row behaves like an array) and JsonSerializable (so it can be handed straight to json_encode / a Laravel response).

First use case — return a statement as a JSON API response without an intermediate mapping layer:

Route::get('/orders/{id}', function (string $id) {
    $statement = Order::query()->where('id', $id)->statement();

    abort_if(! $statement, 404);

    return response()->json($statement); // hits jsonSerialize()
});

That single line is the shortest path to value; everything else is about keeping it predictable.

Implementation Patterns

Statement as a read model, not a mutable array. Because Statement implements ArrayAccess, it is tempting to write to it ($statement['status'] = 'paid'). Treat it as a read-only projection. If you need mutation, hydrate to an array or DTO first, mutate that, and persist explicitly. This keeps the boundary between "query result" and "domain object" honest.

Serialization at the edge only. Let JsonSerializable do its job in controllers and API resources; never let a Statement leak into a Blade view or a job payload. For a stable API contract, wrap it:

return OrderResource::make($statement)->response();

so column additions or renames in the underlying query do not silently change your public JSON shape.

Single-row vs. multi-row access. Use offset access for keyed lookups on a single row and foreach for sets. Do not mix the two idioms inside the same method — it makes it ambiguous whether a null means "no row" or "column is null".

$row = $repository->find($id);        // Statement|null
$total = $row['total'] ?? 0;          // single-row offset access

foreach ($repository->all() as $row) { // iteration
    $totals[] = $row['total'];
}

Fake it in tests. Because the class is ArrayAccess + JsonSerializable, a small test double is cheap and lets you assert both behaviours:

final class FakeStatement implements ArrayAccess, JsonSerializable
{
    public function __construct(private array $data) {}

    public function jsonSerialize(): mixed { return $this->data; }
    public function offsetExists(mixed $offset): bool { return isset($this->data[$offset]); }
    public function offsetGet(mixed $offset): mixed { return $this->data[$offset] ?? null; }
    public function offsetSet(mixed $offset, mixed $value): void { $this->data[$offset] = $value; }
    public function offsetUnset(mixed $offset): void { unset($this->data[$offset]); }
}

Note the mixed signatures — they match what the package now declares, and matching them is how you avoid the warnings this release fixed.

Add the compat check to your own pipeline. The new composer check-runtime-compatibility script autoloads source classes under E_ALL before PHPUnit runs. That is a pattern worth copying into application code: PHPUnit does not fail on E_DEPRECATED, so signature-level rot accumulates silently until a minor PHP bump breaks you in production.

Upgrade workflow. For any 5.x patch bump: composer update → composer check-runtime-compatibility → composer test. If you subclass or decorate Statement, do a grep for extends Statement and inspect every hit before merging — that is where signature drift bites.

Gotchas and Tips

offsetExists and null columns. ArrayAccess is conventionally implemented with isset(), so isset($statement['cancelled_at']) returns false when the column exists but is NULL. Use $statement['cancelled_at'] ?? null for null-safe reads, or ->toArray() if you need true key-presence semantics. This distinction silently breaks "has this been set?" checks in real code.

Subclass signatures are now effectively enforced. If you extend Statement, every overridden method must carry the exact mixed parameter and return types: jsonSerialize(): mixed, offsetExists(mixed $offset): bool, offsetGet(mixed $offset): mixed, offsetSet(mixed $offset, mixed $value): void, offsetUnset(mixed $offset): void. Omitting mixed on a parameter is not the same as declaring it — PHP emits a deprecation for implicitly nullable/inconsistent signatures, and that is precisely what this release cleaned up. Expect a future major to make these errors rather than warnings.

Warnings are invisible under Laravel's default error handling. Laravel converts many notices into ErrorException, but deprecations raised during class autoload (before your handler is registered) often go nowhere. That is why the maintainers added an explicit pre-PHPUnit check. When debugging a signature warning, reproduce with:

php -d error_reporting=E_ALL -d display_errors=1 artisan tinker

Duplicate column names in joins. Offset access is keyed, so SELECT orders.*, users.name collapses name to whichever column lands last. Always alias (users.name as user_name) when you plan to use offset access rather than iteration with positional rows.

Don't iterate and index the same cursor. On a lazily-evaluated statement, $stmt[0] may buffer or rewind the underlying cursor, so a subsequent foreach can yield surprising results. Pick one access style per statement instance.

Serialization can over-share. jsonSerialize() typically returns the full row. If the query selects password_hash, api_token or internal flags, they land in your JSON. Select explicitly rather than SELECT *, or gate with an API resource — the package is not responsible for redacting.

Pin the platform when testing across versions. If CI runs 8.5 but production is 8.3, config.platform.php in composer.json keeps the resolved dependency graph honest. Run the compat check under both the lowest and highest supported PHP to catch both deprecation and missing-feature failures.

Extension points to prefer. Compose rather than inherit: a decorator that wraps Statement and implements the same two interfaces gives you logging, redaction or type-casting without coupling to internal method signatures that the maintainers just proved they will adjust.

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.
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk