- Using a small Symfony installation as possible
- Using SQLite database for simplicity but with price of some caveats
- There are no real decimal or numeric data type so emulation with harcoded 16,8 precision is used
- There are no INSERT IGNORE method so unique constraint violation are just skipped
- There is
\App\Services\RatesUpdater::makeReverseRatemethod to make reverse exchange rate. However, separate buy and sell rates should be used in real life. - There are two tables for rates: rates with provided data and pairs with all currencies combinations (
triangles). Triangulations are implemented in the
\App\Services\RatesTriangulatorservice. It's inspired by http://www.dpxo.net/articles/fx_rate_triangulation_sql.html - There was some date errors in ECB rates so rates' date are writing to the tables but not using in the finally exchange calculation
- There are simple functional tests with fake data from
\App\Providers\FakeRatesProviderprovider
- currency:update - Update currencies exchange rates
- currency:exchange - Exchange currency
And two installation & usage ways: local PHP and Docker.
- PHP 8.1
- ext-bcmath
- ext-ctype
- ext-iconv
- ext-intl
- ext-pdo_sqlite
- ext-simplexml
- ext-sqlite3
- Composer
git clone https://github.com/vladimirmartsul/symfony-exchange-demo.git
cd symfony-exchange-demo
composer install --no-dev --no-interaction
php bin/console doctrine:database:create
php bin/console doctrine:migrations:migrate --no-interactionUpdate currency rates first
php bin/console currency:updateUse
php bin/console currency:exchange <amount> <from> <to>For example
php bin/console currency:exchange 2 EUR BTCshould output
[OK] 2 EUR is 0.00005254 BTCcd symfony-exchange-demo
echo APP_ENV=test > .env.local
composer install --no-interaction
php bin/console doctrine:database:create
php bin/console doctrine:migrations:migrate --no-interaction
php bin/phpunitDocker Desktop (Windows, MacOS) or docker-cli and docker-compose (Linux)
git clone https://[email protected]/vladimirmartsul/symfony-exchange-demo.git
cd symfony-exchange-demo
docker compose up --buildCurrency rates will be updated during build.
docker compose run symfony-exchange-demo currency:exchange <amount> <from> <to>For example
docker compose run symfony-exchange-demo currency:exchange 2 EUR BTCshould output
[OK] 2 EUR is 0.00005254 BTCcd symfony-exchange-demo
echo APP_ENV=test > .env.local
docker compose run symfony-exchange-demo composer install --no-interaction
docker compose run symfony-exchange-demo doctrine:database:create
docker compose run symfony-exchange-demo doctrine:migrations:migrate --no-interaction
docker compose run symfony-exchange-demo bin/phpunitThere is ability to add new exchange rates providers.
The new provider must implement \App\Contracts\RatesProviderInterface interface with constructor __construct(\Symfony\Contracts\HttpClient\HttpClientInterface $client, string $url, string $base) and __invoke(): App\Dto\Rate[] method.
However, in many cases it is enough to extend abstract \App\Providers\RatesProvider class and
implement \App\Providers\RatesProvider::transform(array $data): RateDto[] method.
Additionaly the new provider must be registered in config/services.yaml with its own arguments and app.rates_provider tag. Real params such as URL and base currency must be writen in .env file.