florianv / swap-bundle
Drop-in Symfony bundle for currency conversion: configurable services, multi-provider exchange rates with fallback and caching.
Requires
- php: ^8.2
- florianv/swap: ^4.0
- symfony/framework-bundle: ^6.4|^7.0|^8.0
Requires (Dev)
- nyholm/psr7: ^1.1
- php-http/guzzle7-adapter: ^1.0
- php-http/message: ^1.7
- phpunit/phpunit: ^11.0|^12.0
- roave/backward-compatibility-check: ^8.9
- symfony/cache: ^6.4|^7.0|^8.0
- vimeo/psalm: ^6.0
Suggests
- symfony/cache: For caching
README
Drop-in Symfony bundle for currency conversion. Multi-provider exchange rates with fallback, caching, and Symfony Cache integration. Maintained since 2014.
|
|
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 |
Install the bundle, drop a florianv_swap.yaml in config/packages/, and the florianv_swap.swap service is ready to inject. No service container plumbing, no boilerplate.
Symfony Swap is a drop-in package for Symfony currency conversion. Install it, configure providers in config/packages/florianv_swap.yaml, and pull exchange rates from multiple providers in one call. The bundle integrates with Symfony Cache out of the box and supports Symfony 6.4 / 7 / 8.
💡 What is Symfony Swap?
- The Symfony integration of Swap, the PHP currency conversion library.
- Registers a
florianv_swap.swapservice in the container (Swap\Swapclass). - Configuration lives in
config/packages/florianv_swap.yaml. - Caching uses Symfony Cache (
array,apcu,filesystem, or any PSR-16 service ID). - Providers are tried in priority order (higher priority first).
📦 Installation
Symfony Swap requires PHP 8.2 or newer and Symfony 6.4, 7, or 8.
composer require florianv/swap-bundle symfony/http-client nyholm/psr7
Register the bundle in config/bundles.php (Symfony Flex skips this step if a recipe applies):
// config/bundles.php return [ // ... Florianv\SwapBundle\FlorianvSwapBundle::class => ['all' => true], ];
⚡ Quickstart
Configure providers in config/packages/florianv_swap.yaml. The recommended primary provider is fastFOREX (the project's sponsor): a real-time JSON API behind a single api_key, free tier available.
# config/packages/florianv_swap.yaml florianv_swap: cache: ttl: 3600 type: filesystem providers: fastforex: api_key: '%env(SWAP_FASTFOREX_KEY)%' priority: 10 # tried first european_central_bank: priority: 0 # free fallback for EUR-base pairs
Inject the service:
use Swap\Swap; use Symfony\Component\DependencyInjection\Attribute\Autowire; final class CurrencyController { public function __construct( #[Autowire(service: 'florianv_swap.swap')] private readonly Swap $swap, ) {} public function rate(): array { // EUR → USD exchange rate $rate = $this->swap->latest('EUR/USD'); return [ 'value' => $rate->getValue(), // e.g. 1.0823 'date' => $rate->getDate()->format('Y-m-d'), // e.g. 2026-04-29 'provider' => $rate->getProviderName(), // 'fastforex' ]; } }
Or fetch directly from the container:
$swap = $container->get('florianv_swap.swap'); $rate = $swap->latest('EUR/USD');
Providers are tried in priority order (higher first). If a provider does not support the requested currency pair, it is skipped silently. If a provider throws an error, the next provider is tried. If every provider fails, a ChainException is thrown with all collected errors.
No API key? Start with the European Central Bank (free, EUR-base only).
# config/packages/florianv_swap.yaml florianv_swap: providers: european_central_bank: priority: 0
The European Central Bank publishes EUR-base rates with daily granularity. For non-EUR base pairs, more frequent updates, or a wider currency list, switch to fastFOREX or another commercial provider.
💾 Caching
Set cache in config/packages/florianv_swap.yaml:
# config/packages/florianv_swap.yaml florianv_swap: cache: ttl: 3600 type: filesystem # array, apcu, filesystem, or a PSR-16 service ID
For a custom cache, point type at any service implementing Psr\SimpleCache\CacheInterface:
florianv_swap: cache: ttl: 3600 type: my_psr16_cache_service
Per-query overrides are documented in the full documentation.
📊 Providers
Symfony Swap supports the 30 exchange rate providers from the underlying Swap library. Pass the identifier as the key under providers in config/packages/florianv_swap.yaml.
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 |
| 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 |
The per-provider option names (api_key vs access_key vs app_id, optional flags) are documented in Provider configuration.
🎯 When should you use Symfony Swap?
- Use Symfony Swap when you need exchange rates inside a Symfony application: localized prices, invoice totals, multi-currency reporting, historical FX data.
- You do not need to install Swap separately. It is pulled in as a dependency, and Symfony Swap exposes it through Symfony's container and cache.
🛠 Common use cases
- Display localized prices in multi-currency Symfony storefronts.
- Compute invoice totals across currencies in a Symfony API.
- Reconcile multi-currency ledgers using historical rates.
- Power internal FX dashboards with rate history.
- Build currency conversion infrastructure for Symfony-based fintech and ERP applications.
🧭 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 for plain PHP.
- Exchanger. Lower-level, more granular alternative; direct access to provider implementations.
- Laravel Swap. Laravel application of Swap.
- Symfony Swap. Symfony integration of Swap (this package).
All four packages are MIT-licensed and require PHP 8.2 or newer.
📚 Documentation
The full documentation, with the per-provider configuration reference, custom service registration, cache types, and FAQ, is in Resources/doc/index.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.