bentools / currency
Currency management in PHP.
Installs: 1 486
Dependents: 0
Suggesters: 0
Security: 0
Stars: 3
Watchers: 4
Forks: 1
Open Issues: 0
Requires
- php: >=7.1
- bentools/querystring: ^1.0
- php-http/discovery: ~1.0
- php-http/httplug: ~1.0|~2.0
- php-http/message: ~1.6
- php-http/message-factory: ~1.0
- psr/simple-cache: ^1.0
Requires (Dev)
- bentools/doctrine-static: 1.0.x-dev
- bentools/iterable-functions: ^1.1
- doctrine/orm: ^2.6
- guzzlehttp/guzzle: ~6.3
- php-coveralls/php-coveralls: ^2.1
- php-http/guzzle6-adapter: ~1.1|~2.0
- php-http/mock-client: ~1.1|~2.0
- phpunit/phpunit: ^6.0
- squizlabs/php_codesniffer: ^3.2
- symfony/cache: ^4.0
- symfony/phpunit-bridge: ~4.0
- symfony/var-dumper: ~4.0
This package is auto-updated.
Last update: 2024-12-18 17:15:22 UTC
README
A very simple, framework-agnostic, PHP library to work with currencies.
Install
composer require bentools/currency:1.0.x-dev
Example use
use BenTools\Currency\Converter\CurrencyConverter; use BenTools\Currency\Model\Currency; use BenTools\Currency\Provider\EuropeanCentralBankProvider; use DateTime; $eur = new Currency('EUR'); $usd = new Currency('USD'); $exchangeRateProvider = new EuropeanCentralBankProvider(); $exchangeRate = $exchangeRateProvider->getExchangeRate($eur, $usd, new DateTime('yesterday')); $currencyConverter = new CurrencyConverter($exchangeRate); var_dump($currencyConverter->convert(299, $usd, $eur)); // float(242.67510753997) var_dump($currencyConverter->convert(10.99, $eur, $usd)); // float(13.540779)
bentools/currency
respects SOLID principles. So feel free to implement your own:
- CurrencyInterface (simple value object with a
getCode()
method) - ExchangeRateInterface (value object with source currency, target currency and ratio)
- ExchangeRateFactoryInterface (how to instanciate ExchangeRate objects)
- ExchangeRateProviderInterface (provide live or historical rates)
- CurrencyConverterInterface (to convert from one currency to another)
Online rate providers
We provide adapters for popular API providers:
- European Central Bank - free use without limit, EUR-based, ~32 currencies supported
- Fixer.io* - ~170 currencies supported, including cryptocurrencies, EUR-based in free plan
- CurrencyLayer.com* - ~170 currencies supported, including cryptocurrencies, USD-based in free plan
- OpenExchangeRates.org* - ~200 currencies supported, including cryptocurrencies, USD-based in free plan
* Only free plans are currently supported by the built-in adapters. Feel free to submit a PR for supporting paid plans.
Chained exchange rate provider
This provider allow you to chain providers. The 1st one which returns a result wins.
use BenTools\Currency\Model\Currency; use BenTools\Currency\Provider\ChainedExchangeRateProvider; use BenTools\Currency\Provider\CurrencyLayerProvider; use BenTools\Currency\Provider\EuropeanCentralBankProvider; use BenTools\Currency\Provider\FixerIOProvider; use BenTools\Currency\Provider\OpenExchangeRatesProvider; $eur = new Currency('EUR'); $usd = new Currency('USD'); $providers = [ new EuropeanCentralBankProvider(), new OpenExchangeRatesProvider($openExchangeApiKey), new FixerIOProvider($fixerIoApiKey), new CurrencyLayerProvider($currencyLayerApiKey), ]; $exchangeRateProvider = new ChainedExchangeRateProvider($providers); $exchangeRateProvider->getExchangeRate($eur, $usd);
Average exchange rate provider
Get an average exchange rate from different providers. If you provide a tolerance, an exception will be thrown if the difference between the lowest and the highest rate exceeds it.
use BenTools\Currency\Model\Currency; use BenTools\Currency\Provider\AverageExchangeRateProvider; use BenTools\Currency\Provider\CurrencyLayerProvider; use BenTools\Currency\Provider\EuropeanCentralBankProvider; use BenTools\Currency\Provider\FixerIOProvider; use BenTools\Currency\Provider\OpenExchangeRatesProvider; use DateTimeImmutable; $eur = new Currency('EUR'); $usd = new Currency('USD'); $providers = [ new EuropeanCentralBankProvider(), new OpenExchangeRatesProvider($openExchangeApiKey), new FixerIOProvider($fixerIoApiKey), new CurrencyLayerProvider($currencyLayerApiKey), ]; $tolerance = 0.005; $exchangeRateProvider = AverageExchangeRateProvider::create($tolerance)->withProviders(...$providers); $exchangeRateProvider->getExchangeRate($eur, $usd, new DateTimeImmutable('2018-03-29'))->getRatio();
PSR-16 provider
Cache your exchange rates for the duration of your choice with the PSR-16 decorator:
use BenTools\Currency\Model\Currency; use BenTools\Currency\Provider\EuropeanCentralBankProvider; use BenTools\Currency\Provider\PSR16CacheProvider; use Redis; use Symfony\Component\Cache\Simple\RedisCache; $eur = new Currency('EUR'); $usd = new Currency('USD'); $redis = new Redis(); $redis->connect('localhost'); $ttl = 3600; $provider = new PSR16CacheProvider( new EuropeanCentralBankProvider(), new RedisCache($redis, 'currencies', $ttl) ); $exchangeRate = $provider->getExchangeRate($eur, $usd);
Doctrine ORM provider
If you store your own exchange rates with Doctrine ORM, the built-in implementation may help:
use App\Entity\ExchangeRate; use BenTools\Currency\Model\Currency; use BenTools\Currency\Provider\DoctrineORMProvider; use DateTimeImmutable; $eur = new Currency('EUR'); $usd = new Currency('USD'); $exchangeRateProvider = new DoctrineORMProvider($doctrine, ExchangeRate::class); $exchangeRateProvider->getExchangeRate($eur, $usd, new DateTimeImmutable('2018-03-29'))->getRatio();
Framework agnostic
bentools/currency
leverages HttpPlug to connect to the APIs. This means:
- You're free to use any HTTP client (Guzzle 5, Guzzle 6, React, Zend, Buzz, ...) already existing in your project
- By default,
bentools/currency
will automagically discover the client to use - You can enforce a specific client with its specific configuration in any
ExchangeRateProvider
.
Don't forget that most free plans limit to 1000 calls/month, so you'd better configure your Http Client to cache responses. If you use Guzzle 6+, have a look at kevinrob/guzzle-cache-middleware
Tests
./vendor/bin/phpunit
License
MIT
Disclaimer
This library is intended to be easy to use, and aims at covering most common needs. To achieve this, it uses floats
as type hints (but you're free to store as integers and convert back).
Keep in mind that working with floats can lead to inaccurate results when dealing with a big number of digits. Read this for further information.
$float = 0.1234567890123456789; $factorA = 1000; $factorB = 10000; var_dump(($float * $factorA / $factorA) === $float); // true var_dump(($float * $factorB / $factorB) === $float); // false $integer = 1000000000000; $factorA = 1000000; $factorB = 10000000; var_dump($integer * $factorA === (int) (float) ($integer * $factorA)); // true var_dump($integer * $factorB === (int) (float) ($integer * $factorB)); // false
In short, avoid dealing with big integers or a high number of decimals when using this library if precision matters.