petrepatrasc/blizzard-starcraft-api
Laravel package for the Blizzard StarCraft II API, offering an expressive, testable client to query profiles, ladders, matches, achievements, and other game data. It simplifies authentication and API requests so you can integrate StarCraft II stats into your PHP applications.
Install and configure
composer require <vendor>/<blizzard-api>) and publish its config: php artisan vendor:publish --tag=blizzard-config..env:
BLIZZARD_CLIENT_ID=
BLIZZARD_CLIENT_SECRET=
BLIZZARD_REGION=us
BLIZZARD_LOCALE=en_US
token.cache_key and token.ttl) and that client_id/client_secret are the only required secrets.Where to look first
First use case The lowest-risk first call is a static namespace lookup, which needs no user context:
use Vendor\Blizzard\Facades\Blizzard;
$realm = Blizzard::worldOfWarcraft()->realm('area-52', 'us');
If that returns data, your credentials, region host, and token flow are all wired correctly. Follow it with a profile/character call, because that exercises the namespace and locale parameters that static data calls don't.
Wrap the facade, don't scatter it Inject the client (or a thin repository of your own) into services and jobs rather than calling the facade from controllers. This matters more than usual here: the package performs network I/O and can throw on token expiry, and you want one place that decides whether to retry, cache, or fail.
Cache aggressively, keyed by every variable
Battle.net rate limits are hourly and daily, and character/profile data changes slowly. Cache keyed on endpoint + region + locale + namespace + identifiers:
$key = "blizzard:{$region}:{$locale}:item:{$id}";
return Cache::remember($key, now()->addHours(6), fn () => Blizzard::worldOfWarcraft()->item($id));
Static data (items, spells, mounts) can be cached for days; character profiles for minutes to an hour. Never let two different regions share a cache key — the payloads differ.
Cache the token, not just the response The token endpoint has its own rate limit and returns a 24-hour token. Store it in the cache with a TTL slightly below its real expiry so concurrent workers don't each mint a new one. If 1.1.0's token integration doesn't already do this, wrap it.
Queue bulk work Any "sync a guild roster" or "backfill 500 items" job belongs on a queue worker with a rate limiter, not a request cycle:
RateLimiter::for('blizzard', fn () => Limit::perMinute(90)->by('blizzard'));
A withoutOverlapping() middleware plus a per-region limiter keeps you safely under the published limits and prevents 429 storms when a backfill job fans out.
Handle 401 vs 404 vs 429 distinctly A 401 usually means a stale token — clear the token cache and retry once. A 404 on a character endpoint is frequently a private profile rather than a missing character; surface that distinction to your users instead of a generic "not found". A 429 should back off and re-queue, not throw into the request.
Testing
Because 1.1.0 replaced file_get_contents with a bespoke cURL layer, Http::fake() will not intercept these calls — they don't go through Laravel's HTTP client. Bind a fake connector against the package's interface in your test case, or use a recorded fixture at the connector boundary. Build this harness early; it is the single biggest quality-of-life factor for day-to-day work with this package.
file_get_contents is a genuine improvement (it was frequently disabled by allow_url_fopen=0 on hardened hosts), but verify ext-curl is installed in every environment, including your CI image and any minimal Docker base. Failures here surface as an unexplained empty response rather than a clear error.namespace=static-us / dynamic-us / profile-us produces confusing 404s. Check whether the package infers the namespace from the endpoint or whether you must pass it; if inferred, pin the behaviour in a test.us, eu, kr, tw, cn are separate hosts with separate data and separate rate-limit buckets. Derive region per-call for multi-region features instead of relying on the single config default.file_get_contents, or relied on a manually pasted token, you'll need changes. Pin ^1.1 and read the connector diff.curl.cainfo / openssl.cafile) rather than disabling CURLOPT_SSL_VERIFYPEER. This class of "fix" gets copy-pasted into production and never removed.How can I help you explore Laravel packages today?