liberusoftware/currency-context-api
A Laravel package that resolves and applies a request-scoped currency context, letting you detect, set, and share the active currency across middleware, facades, and helpers so pricing and formatting stay consistent throughout each request.
composer require liberusoftware/currency-context-api then immediately read vendor/liberusoftware/currency-context-api/composer.json — that tells you the real namespace, the extra.laravel auto-discovery entries (service provider, facade alias), and the PHP/Laravel version constraints. With zero stars and no dependents, the source is the documentation.JsonResource/transformer classes. Run php artisan list and look for a new command group; grep the source for Route::, Middleware, Facade, and Resource to map the surface in five minutes.php artisan vendor:publish --provider="LiberuSoftware\CurrencyContextApi\...ServiceProvider" (grab the FQCN from composer.json). If no tag exists, copy the config file manually and register it in your own provider — that's your override point for base currency, default locale, and any upstream endpoint/timeout.Middleware-driven context. The cleanest integration is one middleware that populates the currency context per request (from user preference → session → Accept-Language/geo header → config default, in that order) and pushes it into the container. Register it in the web group or per-route. Keep the resolution order in your app, not in the package, so it's testable and swappable.
Constructor injection over the facade. Resolve the context contract through the container in services and jobs; use the facade only in controllers and Blade. This keeps queue workers and console commands from silently using a stale/default context.
API resources as the primary output. If the package ships resources/transformers, extend them rather than duplicating formatting logic:
class PriceResource extends CurrencyResource
{
public function toArray($request): array
{
return parent::toArray($request) + [
'formatted' => $this->formatMoney($this->amount),
];
}
}
Validation. Pair it with a currency-code rule (ISO 4217) for any user-editable currency field, and reject codes the context adapter can't resolve rather than letting them fail at render time.
Testing. Bind a fake context in a test service provider:
$this->app->instance(CurrencyContext::class, new FakeContext('GBP'));
Then assert formatting, rounding, and JSON shape without touching the network. If the adapter makes outbound calls, use Http::fake() in a base test case so the whole suite is deterministic.
Multi-tenant / multi-currency. Store the currency per user or per tenant record, not per session only — session-scoped currency breaks on queued jobs, PDF generation, and API tokens. Serialize the resolved currency onto the job payload.
Cache the resolved context, not the rates. Context resolution is cheap and request-scoped; exchange rates are expensive and volatile. Cache rates with a short TTL and a stale-while-revalidate fallback, and always keep the last-known rate so a failing upstream endpoint degrades to slightly-wrong prices instead of a 500.
NOASSERTION. That is not a permissive license — it means the repository's licensing metadata doesn't map to a recognised SPDX identifier. Read the actual LICENSE file before shipping this to production, and get sign-off if it's commercially sensitive.composer.json, commit the lock file, and be prepared to vendor the source into your own namespace. Budget for maintaining it.composer show liberusoftware/currency-context-api --all) before assuming version constraints will work. If releases are tags-only without composer.lock-safe metadata, use a commit hash.php artisan about doesn't list the provider, register it manually in bootstrap/providers.php (Laravel 11+) or config/app.php. A missing provider manifests as "target class does not exist" on the facade, which is easy to misdiagnose as a namespace typo.config:cache hides late-bound config. Anything read at boot (default currency, base currency) is frozen. If you change currency per tenant at runtime, read it from the context resolver, never from config() inside a request.Brick\Money/MoneyPHP) and use the package only for presentation. Never let a presentation adapter own arithmetic.de_DE locale does not imply EUR, and formatting 1.234,56 with an en_US locale produces nonsense. Resolve them separately and pass both into the formatter.Log::debug() at the middleware boundary dumping {user_id, session_currency, resolved_currency, source}. Ninety percent of "wrong price shown" reports are a resolution-order bug, not a formatting bug.How can I help you explore Laravel packages today?