The bridge ships a route binding that turns a route parameter into a SteamId before it reaches your controller — no manual parsing, no validation boilerplate.

  1. Publish the config and flip enabled:

    config/steam-api.php
    'route_binding' => [
    'enabled' => false,
    'enabled' => true,
    'parameter' => 'steamId',
    ],

    parameter is the segment name to claim. It applies to every route using that name, so pick one your application does not already use.

  2. Name a route parameter steamId and type-hint the value object:

    routes/web.php
    use Fkrzski\LaravelSteamApiSdk\Facades\Steam;
    use Fkrzski\SteamApiSdk\ValueObjects\SteamId;
    Route::get('/players/{steamId}', function (SteamId $steamId) {
    return Steam::users()->summaries([$steamId]);
    });

/players/76561198000000000 now hands your closure a ready SteamId. Resolution runs through SteamId::tryFromInput, so a /profiles/<id> URL works too — with whatever trails the ID, be it a sub-path, a ? query string or a # fragment. Anything unresolvable aborts with a 404, exactly as a missing model would.

The binder never calls the Steam Web API — it parses the segment and nothing more:

/players/76561198000000000 → SteamId
/players/gaben → 404

Fkrzski\LaravelSteamApiSdk\Contracts\SteamIdBinder is pulled from the container on every request. One method — __invoke(string $value): SteamId, throwing Symfony\Component\HttpKernel\Exception\NotFoundHttpException on input it cannot resolve.

Wrap the shipped binder instead of reimplementing it — then you only pay for an API call on what it rejects:

app/Routing/VanityAwareSteamIdBinding.php
namespace App\Routing;
use Fkrzski\LaravelSteamApiSdk\Contracts\SteamIdBinder;
use Fkrzski\LaravelSteamApiSdk\Facades\Steam;
use Fkrzski\LaravelSteamApiSdk\Routing\SteamIdRouteBinding;
use Fkrzski\SteamApiSdk\Exceptions\SteamUserNotFoundException;
use Fkrzski\SteamApiSdk\ValueObjects\SteamId;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
final readonly class VanityAwareSteamIdBinding implements SteamIdBinder
{
public function __construct(private SteamIdRouteBinding $binding) {}
public function __invoke(string $value): SteamId
{
try {
return ($this->binding)($value);
} catch (NotFoundHttpException) {
// Neither an ID nor a profile URL — try it as a vanity name.
}
try {
return Steam::users()->resolveVanityUrl($value);
} catch (SteamUserNotFoundException) {
throw new NotFoundHttpException(sprintf('"%s" is not a Steam profile.', $value));
}
}
}

Register it in a service provider:

app/Providers/AppServiceProvider.php
use App\Routing\VanityAwareSteamIdBinding;
use Fkrzski\LaravelSteamApiSdk\Contracts\SteamIdBinder;
$this->app->bind(SteamIdBinder::class, VanityAwareSteamIdBinding::class);

Vanity routes now cost a Steam call per request — cache the resolution if the route is hot.

Terminal window
php artisan about --only=steam_api
php artisan about --only=steam_api
Route Binding ..................................... enabled (steamId)