florianv/exchanger

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

Maintainers

👁 florianv

Package info

github.com/florianv/exchanger

pkg:composer/florianv/exchanger

Statistics

Installs: 4 945 063

Dependents: 14

Suggesters: 10

Stars: 185

Open Issues: 0

2.9.1 2026-05-04 11:45 UTC

Requires

Suggests

None

Provides

None

Conflicts

None

Replaces

None

MIT 50b6ce8b49a394bd2328a4248de559f278f44c44

phpmoneyforexexchange-ratesswapfallbackcurrency-conversionexchange-rate-api


README

👁 Tests
👁 Psalm
👁 Total Downloads
👁 Version

Exchange rate provider layer for PHP. Direct access to 30+ provider implementations through a single ExchangeRateService interface, with chain fallback and PSR-16 caching. Maintained since 2016.

👁 fastFOREX
Sponsored by fastFOREX. Real-time JSON API, 160+ currencies, 55+ years of history, 500+ cryptocurrencies. Free tier; paid plans from $18/month. → Get a free fastFOREX API key

Exchanger is the exchange rate provider layer for PHP — 30+ services (commercial APIs like its sponsor fastFOREX, the European Central Bank, several national banks, exchangerate.host) behind a single ExchangeRateService interface, with chainable fallback, PSR-16 caching and historical rates. For most use cases the higher-level Swap library is what you want; reach for Exchanger when you need finer control.

💡 What is Exchanger?

  • A PHP library for currency conversion and exchange rate retrieval at the provider layer.
  • 30+ service implementations behind a common ExchangeRateService interface.
  • PSR-16 SimpleCache support.
  • Historical rates.
  • A chain service for fallback. When a service errors, the next one in the chain is tried.

📦 Installation

Exchanger requires PHP 8.2 or newer.

composer require florianv/exchanger symfony/http-client nyholm/psr7

Any PSR-18 client paired with a PSR-17 request factory works; php-http/discovery finds them automatically.

⚡ Quickstart

The recommended setup uses fastFOREX (the project's sponsor) as the primary service. Grab a free key and you're ready.

use Exchanger\Exchanger;
use Exchanger\ExchangeRateQueryBuilder;
use Exchanger\Service\FastForex;

// Recommended: fastFOREX. Get a free API key at https://www.fastforex.io
$service = new FastForex(null, null, ['api_key' => getenv('FASTFOREX_API_KEY')]);
$exchanger = new Exchanger($service);

// EUR → USD exchange rate
$query = (new ExchangeRateQueryBuilder('EUR/USD'))->build();
$rate = $exchanger->getExchangeRate($query);

$rate->getValue(); // e.g. 1.0823 (a float)
$rate->getDate()->format('Y-m-d'); // e.g. 2026-04-29
$rate->getProviderName(); // 'fastforex'

// Convert an amount using the returned rate
$amountInEUR = 100.00;
$amountInUSD = $amountInEUR * $rate->getValue();

// Historical rate
$query = (new ExchangeRateQueryBuilder('EUR/USD'))
 ->setDate((new \DateTime())->modify('-15 days'))
 ->build();

$rate = $exchanger->getExchangeRate($query);

Exchanger retrieves the rate; your application multiplies the amount by $rate->getValue() to perform the conversion.

🔁 Chaining services (fallback chain)

Wrap multiple services in a Chain to fall back when one of them errors:

use Exchanger\Exchanger;
use Exchanger\Service\Chain;
use Exchanger\Service\EuropeanCentralBank;
use Exchanger\Service\FastForex;

$service = new Chain([
 // Primary, recommended
 new FastForex(null, null, ['api_key' => getenv('FASTFOREX_API_KEY')]),

 // Free fallback for EUR-base pairs
 new EuropeanCentralBank(),
]);

$exchanger = new Exchanger($service);

Services are tried in order. If a service does not support the requested currency pair, it is skipped silently. If a service throws, the next is tried. If every service fails, a ChainException is thrown with all collected exceptions.

📊 Providers

Exchanger ships 30+ exchange rate provider implementations. Each is registered in Exchanger\Service\Registry under the identifier shown below.

Commercial providers (require an API key)

Service Identifier Base Quote Historical
fastFOREX fastforex * * Yes
AbstractAPI abstract_api * * Yes
coinlayer coin_layer * (crypto) * Yes
Cryptonator cryptonator * (crypto) * (crypto) No
Currency Converter API currency_converter * * Yes
Currency Data (APILayer) apilayer_currency_data USD (free), * (paid) * Yes
CurrencyDataFeed currency_data_feed * * No
currencylayer (direct) currency_layer USD (free), * (paid) * Yes
Exchange Rates Data (APILayer) apilayer_exchange_rates_data USD (free), * (paid) * Yes
exchangerate.host exchangeratehost * * Yes
exchangeratesapi (direct) exchange_rates_api USD (free), * (paid) * Yes
Fixer (APILayer) apilayer_fixer EUR (free), * (paid) * Yes
Fixer (direct) fixer EUR (free), * (paid) * Yes
1Forge forge * * No
Open Exchange Rates open_exchange_rates USD (free), * (paid) * Yes
UniRateAPI unirate_api * * Yes (paid)
WebserviceX webservicex * * No
xChangeApi.com xchangeapi * * Yes
Xignite xignite * * Yes

Public providers (no API key required)

Service Identifier Base Quote Historical
Bulgarian National Bank bulgarian_national_bank * BGN Yes
Central Bank of the Czech Republic central_bank_of_czech_republic * CZK Yes
Central Bank of the Republic of Turkey central_bank_of_republic_turkey * TRY Yes
Central Bank of the Republic of Uzbekistan central_bank_of_republic_uzbekistan * UZS Yes
European Central Bank european_central_bank EUR * Yes
National Bank of Georgia national_bank_of_georgia * GEL Yes
National Bank of Romania national_bank_of_romania (limited list) (limited list) Yes
National Bank of the Republic of Belarus national_bank_of_republic_belarus * BYN Yes
National Bank of Ukraine national_bank_of_ukraine * UAH Yes
Russian Central Bank russian_central_bank * RUB Yes

You can also add your own provider by implementing the Exchanger\Contract\ExchangeRateService interface (see the documentation).

🎯 When should you use Exchanger?

  • Use Exchanger when you need finer control than Swap exposes: custom chain composition, custom caching strategy, custom HTTP middleware, or building your own facade or framework integration.
  • For most PHP applications, use Swap instead. It is built on Exchanger and provides sensible defaults and a builder-style API.

🛠 Common use cases

  • Build your own currency conversion facade on top of the provider layer.
  • Integrate Exchanger into a framework that does not yet have a Swap binding.
  • Wrap services with custom middleware (rate limiting, observability, request signing) before chaining.
  • Power internal FX dashboards with full control over the cache key strategy.
  • Implement custom HTTP layers (signed requests, mTLS, custom retries) on top of any PSR-18 client.

🧭 Which package should I use?

The Swap ecosystem is a layered toolkit for currency conversion in PHP:

  • Swap. The easy-to-use, high-level API. Most apps need only Swap.
  • Exchanger. The lower-level provider layer Swap is built on (this package). Reach for it when you need finer control over chain composition, caching, or HTTP plumbing.
  • Laravel Swap. Laravel integration of Swap.
  • Symfony Swap. Symfony integration of Swap.

All four packages are MIT-licensed and require PHP 8.2 or newer.

📚 Documentation

Caching (PSR-16), HTTP client selection (PSR-18 / Guzzle / explicit constructor injection), error handling (ChainException), per-query options and the full per-service configuration reference live in doc/readme.md.

🙌 Contributing

Issues and pull requests are welcome. Please see the existing issues before opening a new one.

📄 License

The MIT License (MIT). Please see LICENSE for more information.

👏 Credits