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

Exchanger Laravel Package

florianv/exchanger

PHP exchange rate provider layer exposing 30+ services (fastFOREX, ECB, national banks) through one ExchangeRateService interface, with chain fallback, PSR-16 caching and historical rates. Maintained since 2016; requires PHP 8.2+.

View on GitHub
Deep Wiki
Context7

PHP exchange rate provider layer for currency conversion: 30 services, chain fallback, and caching.

Frequently asked questions about Exchanger
How do I install florianv/exchanger in a Laravel application?
Run composer require florianv/exchanger symfony/http-client nyholm/psr7; the library requires PHP 8.2 or newer. No hard HTTP client is bundled, so php-http/discovery (Psr18ClientDiscovery since 2.9.0) locates an installed PSR-18 client, and Laravel already ships Guzzle by default. Exchanger publishes no service provider, so you write a small provider (roughly 30 to 60 lines) that binds a configured Chain instance and reads provider credentials from config/services.php and .env.
Is florianv/exchanger a Laravel package?
No. Exchanger is a framework-agnostic PHP provider layer sitting at the bottom of the florianv stack (laravel-swap, symfony-swap, swap, exchanger) with no facade, config file or auto-discovery. Choosing it directly means you own the DI bindings, config surface, cache policy and chain composition. If you just need to convert an amount at today's rate, laravel-swap is the cheaper decision and pulls Exchanger in transitively.
What PHP and Laravel versions does florianv/exchanger support?
Exchanger requires PHP 8.2 or newer since version 2.9.0, and because it is framework-agnostic it runs in any modern Laravel release. Versioning discipline is decent but not semver-perfect: 2.9.0 raised the PHP floor and swapped the HTTP discovery class in a minor release, both of which can break a dependent app. Pin to a caret range and treat every minor upgrade as a change that needs a full test-suite run.
How do I set up chain fallback between exchange rate providers in Exchanger?
Exchanger ships a Chain service: you compose an ordered list of ExchangeRateService implementations and, when one errors, the next in the chain is tried. Build that chain in your own Laravel service provider, ordering providers by reliability and cost (for example a commercial API first, ECB or a national bank as backup). Caching results on top of the chain keeps you well inside free-tier rate limits and reduces exposure to any single provider outage.
How do I use Laravel's cache with Exchanger's PSR-16 requirement?
Laravel's cache repository implements PSR-16 only partially, so it cannot be passed to Exchanger directly. You have three options: symfony/cache adapters pointed at Redis or the filesystem, which duplicates your cache infrastructure; php-cache/simple-cache-bridge, which goes the wrong direction (PSR-6 to PSR-16); or a small adapter class implementing Psr\SimpleCache\CacheInterface over Illuminate\Contracts\Cache\Repository. The adapter is the right call because TTL, key prefixing and eviction stay under config/cache.php and your existing Redis and Horizon observability keeps working.
Can I get historical exchange rates with florianv/exchanger?
Yes, historical rates are a built-in feature: you build the request with ExchangeRateQueryBuilder and pass the date you want. Support varies by provider, since not all of the 30+ services expose history and free tiers often limit the range, so keep a chain rather than relying on a single source. Chain fallback and PSR-16 caching apply to historical lookups the same way they do for current rates.
How do I fake exchange rates when testing Laravel code that uses Exchanger?
Because the abstraction surface is tiny, you fake it rather than mock HTTP. Bind a stub ExchangeRateService or your own FxRateProvider wrapper in the container that returns fixed ExchangeRate value objects exposing getValue(), getDate(), getProviderName() and getCurrencyPair(). Nothing is hard-coupled to Guzzle or a specific cache backend, so tests run without network access and without a live provider key.
How should I handle rounding and precision when converting currency with Exchanger?
Exchanger returns a rate and nothing more: it does not convert, round or enforce precision, and getValue() returns a float by design. That is fine for display prices and catalog estimates, but it is not ledger-grade accounting. Do the multiplication and rounding at your own boundary with BCMath or brick/money and never let a float reach a persisted monetary column.
What is the difference between exchanger, swap and laravel-swap?
Exchanger is the provider layer with the 30+ service implementations; swap builds conversion and currency logic on top of it, and laravel-swap wires swap into Laravel with a facade, config and container bindings. Reach for Exchanger directly only if you need non-default chain ordering, per-currency-pair cache keys or TTLs, your own PSR-18 middleware for rate limiting, signing or tracing, or a shared FX surface other teams consume. Otherwise laravel-swap gives you the same providers with far less code you own.
Is florianv/exchanger maintained and safe to use in production?
It has been maintained since 2016 under the MIT license with a deliberately small security surface: outbound HTTP only, no PII handling, no deserialization, and API keys as the only secret to protect. The risks are operational rather than code quality: a single primary maintainer with a modest adoption footprint, plus structural provider churn such as 2.0.0 dropping Yahoo and Google and 2.9.0 patching National Bank of Romania endpoints that may stop at any time. Pin the version, keep a fallback chain, and hide the library behind your own FxRateProvider interface so replacing it costs days rather than weeks.
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.
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus