https://github.com/florianv/exchanger
:office: Currency exchange rates framework for PHP
https://github.com/florianv/exchanger
conversion currency currency-exchange-rates exchange-rates money php
Last synced: about 1 month ago
JSON representation
:office: Currency exchange rates framework for PHP
- Host: GitHub
- URL: https://github.com/florianv/exchanger
- Owner: florianv
- License: mit
- Created: 2016-09-06T00:47:59.000Z (almost 10 years ago)
- Default Branch: master
- Last Pushed: 2024-08-01T12:11:58.000Z (almost 2 years ago)
- Last Synced: 2025-04-01T00:38:03.667Z (about 1 year ago)
- Topics: conversion, currency, currency-exchange-rates, exchange-rates, money, php
- Language: PHP
- Homepage: https://florianv.github.io/exchanger/
- Size: 871 KB
- Stars: 185
- Watchers: 12
- Forks: 81
- Open Issues: 7
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# Exchanger
[](https://github.com/florianv/exchanger/actions/workflows/tests.yml)
[](https://github.com/florianv/exchanger/actions/workflows/psalm.yml)
[](https://packagist.org/packages/florianv/exchanger)
[](https://packagist.org/packages/florianv/exchanger)
> _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._
Exchanger is the **exchange rate provider layer** for PHP. It exposes 30 services (the European Central Bank, several national banks, exchangerate.host, and commercial **exchange rate APIs** that require an API key) behind a single `ExchangeRateService` interface, with chainable fallback, PSR-16 caching, and historical rates. Used in real-world PHP applications since 2016.
For most use cases, the higher-level [Swap](https://github.com/florianv/swap) library is what you want. Reach for Exchanger directly when you need finer control.
## 💡 What is Exchanger?
- Exchanger is a PHP library for currency conversion and exchange rate retrieval at the provider layer.
- It contains 30 service implementations behind a common `ExchangeRateService` interface.
- It caches results via PSR-16 SimpleCache.
- It supports historical rates.
- It supports a chain service for fallback. When a service errors, the next one in the chain is tried.
## 🎯 When should you use Exchanger?
- Use Exchanger when you need finer control than [Swap](https://github.com/florianv/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](https://github.com/florianv/swap) instead. It is built on Exchanger and provides sensible defaults and a builder-style API.
## 🧠 Why Exchanger over Swap?
Swap is the easy-to-use, high-level API. Exchanger is the layer Swap is built on.
Reach for Exchanger directly when:
- **Custom facade:** you want to build your own currency conversion API on top of the provider layer.
- **Framework binding:** you are integrating into a framework that does not yet have a Swap binding.
- **Fine-grained chain composition:** you need to wrap services with custom logic (rate limiting, observability, conditional fallback) before chaining them.
- **Direct cache control:** you want to manage the PSR-16 cache key strategy yourself.
- **Custom HTTP layer:** you need an HTTP middleware stack the Swap builder does not expose.
If none of these apply, use Swap.
## 📦 Installation
Exchanger requires PHP 8.2 or newer.
```bash
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
```php
use Exchanger\Exchanger;
use Exchanger\ExchangeRateQueryBuilder;
use Exchanger\Service\EuropeanCentralBank;
// The European Central Bank is free, no API key required.
$service = new EuropeanCentralBank();
$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(); // 'european_central_bank'
// 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:
```php
use Exchanger\Exchanger;
use Exchanger\Service\Chain;
use Exchanger\Service\EuropeanCentralBank;
$service = new Chain([
new YourPrimaryService(null, null, ['api_key' => 'YOUR_KEY']),
new YourFallbackService(null, null, ['api_key' => 'YOUR_KEY']),
new EuropeanCentralBank(), // free fallback for EUR-base pairs
]);
$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 an exception, the exception is collected and the next service is tried. If every service was skipped or threw, the chain raises an `Exchanger\Exception\ChainException` containing all collected exceptions.
## 🛠 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, more granular 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 application of Swap.
- **Symfony Swap.** Symfony integration of Swap.
All four packages are MIT-licensed and require PHP 8.2 or newer.
## 📊 Providers
Exchanger ships 30 exchange rate provider implementations. Each is registered in `Exchanger\Service\Registry` under the **identifier** shown in the table.
### 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 |
| Cryptonator | `cryptonator` | * (crypto) | * (crypto) | No |
| European Central Bank | `european_central_bank` | EUR | * | Yes |
| exchangerate.host | `exchangeratehost` | * | * | 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 |
| WebserviceX | `webservicex` | * | * | No |
### Commercial providers (require an API key)
| Service | Identifier | Base | Quote | Historical |
| -------------------------------- | -------------------------------- | --------------------- | ----- | ---------- |
| AbstractAPI | `abstract_api` | * | * | Yes |
| coinlayer | `coin_layer` | * (crypto) | * | Yes |
| 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 |
| exchangeratesapi (direct) | `exchange_rates_api` | USD (free), * (paid) | * | Yes |
| fastFOREX.io | `fastforex` | * | * | 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 |
| xChangeApi.com | `xchangeapi` | * | * | Yes |
| Xignite | `xignite` | * | * | Yes |
You can also add your own provider by implementing the `Exchanger\Contract\ExchangeRateService` interface (see the [documentation](doc/readme.md)).
## ⚙ Caching, HTTP client, and error handling
- **Caching:** PSR-16 `SimpleCache` is passed as the second constructor argument: `new Exchanger($service, $cache)`. Per-query disable: `->addOption('cache', false)`. Per-query TTL: `->addOption('cache_ttl', 3600)`.
- **HTTP client:** any PSR-18 client (`symfony/http-client`, `php-http/guzzle7-adapter`, etc.). Pass it explicitly to each service constructor, or rely on `php-http/discovery` to auto-discover.
- **Errors:** when every service in a `Chain` has either skipped (unsupported pair) or thrown, the chain raises an `Exchanger\Exception\ChainException` containing all collected exceptions.
## 📚 Documentation
The full documentation, with the per-provider configuration reference, caching options, and how to write your own service, is in [doc/readme.md](doc/readme.md).
## 🧩 Related packages
The Swap ecosystem:
- [**Swap**](https://github.com/florianv/swap): easy-to-use PHP currency conversion library.
- [**Exchanger**](https://github.com/florianv/exchanger): exchange rate provider layer (this package).
- [**Laravel Swap**](https://github.com/florianv/laravel-swap): Laravel application of Swap.
- [**Symfony Swap**](https://github.com/florianv/symfony-swap): Symfony integration of Swap.
## 🤝 Sponsorship
The Swap ecosystem is open to selected sponsorships from exchange rate API providers and financial infrastructure companies.
Sponsorship can include:
- Documentation visibility
- Integration examples
- Ecosystem-level visibility across Swap, Exchanger, Laravel Swap, and Symfony Swap
For inquiries, contact the maintainer via [GitHub](https://github.com/florianv).
## 🙌 Contributing
Issues and pull requests are welcome. Please see the existing [issues](https://github.com/florianv/exchanger/issues) before opening a new one.
## 📄 License
The MIT License (MIT). Please see [LICENSE](https://github.com/florianv/exchanger/blob/master/LICENSE) for more information.
## 👏 Credits
- [Florian Voutzinos](https://github.com/florianv)
- [All contributors](https://github.com/florianv/exchanger/contributors)