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

Utils Laravel Package

rokka/utils

Utility helpers for the Rokka image service in PHP, providing small reusable functions and classes to simplify common image URL, stack, and configuration tasks in your applications.

View on GitHub
Deep Wiki
Context7

Getting Started

rokka/utils is a deliberately small helper library that sits beside the official rokka-io/rokka-client-php. It does not talk to the Rokka API on its own; it provides the small, boring, shared pieces (URL/stack/hash helpers, signed-URL generation, format/option normalization) that every Rokka-backed project ends up re-implementing.

  1. Install both packages together — utils is only useful when paired with the client or with your own Rokka HTTP calls:

    composer require rokka-io/rokka-client-php rokka-io/rokka-utils-php:^1.0.3
    

    Take 1.0.3 or newer. It contains a small but important fix (UTC timezone handling in SignURL); anything older will produce wrong signatures on non-UTC servers.

  2. Before writing code, read src/ top to bottom. The package is small enough that the entire public surface fits on one screen. This is the single most important step: unlike larger libraries, there is no meaningful documentation site, so the source and tests/ are the spec. Tests show the exact expected string output for URLs, stack names, signature parameters, and option handling.

  3. Check composer.json for the PHP constraint and dependencies. The package is still receiving patch releases (1.0.3), so it is at least nominally maintained — but confirm the constraint satisfies your app (Laravel 10/11/12 on PHP 8.1+). Verify no deprecated constructs (implicitly nullable params, dynamic properties) before relying on it in production.

  4. Your first real use case is almost always URL construction: given an organization, a stack name, an image hash, and a format, produce the correct Rokka CDN URL (and its variants for srcset). Build that one function first, assert it against a known-good URL from the Rokka dashboard, and use it as your integration anchor before adopting any other helper.

  5. The second use case that surprises people is signed URLs for private stacks. Find the SignURL helper early, even if you are on a public stack today — switching a stack to private later is a config change, and you do not want to discover then that signing was never wired up.

If the source does not actually cover the helper you need, that is a signal: add the helper in your own app rather than forking a small, thinly-used package.

Implementation Patterns

Treat it as a pure-function utility layer, not a service. These helpers should be stateless and deterministic. Keep the Rokka client for uploads, stack mutations, and metadata; keep utils for string shaping. Do not mix the two concerns in the same class.

Wrap the organization in config. Rokka URLs embed the org name. Put services.rokka.org, services.rokka.api_key, services.rokka.default_stack, and (if you use private stacks) services.rokka.signing_key in config/services.php, read from .env, and have your helpers accept the org as a parameter (or read it from a small injected config object). Never hardcode the org in Blade templates.

Blade and view integration. The highest-leverage pattern is a Rokka facade or a single rokka_image() helper that composes the utils calls:

// app/Support/Rokka.php
public static function image(string $hash, string $stack, string $format = 'webp'): string
{
    return \Rokka\Utils\... // use the URL helper from the package
        ?? sprintf('https://%s.rokka.io/%s/%s.%s', config('services.rokka.org'), $stack, $hash, $format);
}

That fallback matters: it keeps your templates working even if the helper signature moves or the package is later removed.

Signed URLs for private stacks. Wrap the signing helper behind the same class and return a fully-qualified, signed URL rather than signing at the call site. Keep the signing key server-side only — a signed URL is a bearer credential for that image/option combination, so never emit the key into HTML or JS. Sign with a short expiry and cache the signed string no longer than that expiry.

Srcset and responsive images. The pattern that pays for itself is generating a srcset array from one stack plus a set of format/width options. Loop over [320, 640, 1280, 1920], call the URL helper for each, and emit srcset/sizes in the Blade component. Cache the resulting string per (hash, stack, variant, expiry) key if you render the same image repeatedly.

Testing. Because the helpers are deterministic, they are ideal for unit tests. Snapshot the generated URLs, then diff against the Rokka dashboard once. Add a frozen-time test for signed URLs — that is exactly the class of bug 1.0.3 fixed, and a clock-sensitive test is what catches the next one. In feature tests, assert that the URL is generated, not that the CDN returns the image. Add a single integration test behind an env flag (ROKKA_INTEGRATION=true) that actually requests the URL and checks for a 200.

Pairing with the client. A clean division: on upload, the client returns a hash; immediately persist that hash plus the stack name (never construct hashes from the original filename). All subsequent rendering goes through utils. Stack definitions stay versioned in your repo and are pushed via the client in a deploy command, not hand-edited in the dashboard.

Migration safety. Wrap the package behind one class in app/Support. That gives you a single file to change if you drop the dependency, upgrade it, or move to your own helpers.

Gotchas and Tips

  • Signed-URL timezone (fixed in 1.0.3). SignURL now sets UTC before computing timestamps. If you are on an older version and your app timezone is not UTC (config('app.timezone') defaults to UTC in Laravel, but plenty of apps override it), signatures will be silently wrong and the CDN will return 403 — not a useful error. Upgrade, and if you cannot, set date_default_timezone_set('UTC') around the signing call.
  • Signature drift is a clock problem first. Expiry is embedded in the signed URL. A server with skewed NTP, or a signature minted during a DST transition, will fail even with the fix. Assert abs(now()->diffInSeconds(Carbon::now())) < 5 in your deploy smoke test rather than debugging this through the CDN.
  • Patching is not the same as maintained. There is still a single maintainer, a small install base, and no documentation. Treat this as an internal-style utility: pin a tight range in composer.json and commit the lockfile. Do not let composer update pull behavioral changes into URL or signature generation.
  • No documentation means no contract. The public API may be loose (public methods that were never meant to be public, or return types that change). Read the source, and copy the three or four helpers you actually use into app/Support if the surface is too broad. A 100-line local copy beats a dependency you cannot reason about. The 1.0.3 fix is a good illustration: it changed behaviour inside a helper without any signature change, discoverable only by reading the diff.
  • PHP version drift. Confirm the package still parses on your PHP version. Old packages often rely on implicitly nullable parameters (Type $x = null) which are deprecated in PHP 8.4. Run vendor/bin/phpstan or simply exercise every helper in a test to smoke out notices.
  • URL escaping and format strings. The most common failure is a malformed URL from an unexpected format value (e.g. a leading dot, mixed case, or a query option appended in the wrong order). Log the raw URL before it hits the template and compare it character-by-character with a dashboard-generated one. Do not assume the package normalizes formats — check.
  • Rokka's URL grammar. https://{org}.rokka.io/{stack}/{hash}.{format} with optional query options (?width=...&height=...). If you generate URLs manually, keep the hash as-is (do not lowercase or trim it) and let the CDN validate. A silently altered hash returns a 404 from the CDN, which looks like a stack problem but is a string problem.
  • Caching and invalidation. CDN URLs are immutable per hash, which is a feature: render them into Cache-Control: public, max-age=31536000, immutable. But if you cache the generated URL string in Redis, include the stack name in the key — stack definitions change, and a stale stack name will 404 after a deploy. Signed URLs must be cached with an expiry shorter than the signature lifetime.
  • Stack mutations are not cache-aware. Changing a stack definition via the client invalidates cached derivatives on Rokka's side, but not your own rendered HTML. Bust your view/response cache on stack deploy.
  • Extension points are minimal. There is no service provider, config, or container binding — do not expect php artisan vendor:publish to do anything. Wire configuration yourself in config/services.php and your own provider.
  • Debugging checklist. 1) Print the exact URL (query string and signature included). 2) curl -I it and check status + X-Rokka-* headers. 3) If it 404s, test the same stack/hash pair in the Rokka dashboard. 4) If it 403s, separate the two causes: wrong org / private stack (config), versus an expired or timezone-shifted signature (clock). 5) Re-sign with a fresh timestamp before concluding the package is broken.
  • Vendor risk. If this package disappears or you must drop it, you need an exit. Keeping usage confined to one wrapper class means the exit is a one-file rewrite; scattering helper calls through templates means a multi-day refactor. Plan for removal from day one.
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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core