sfynx-project/tool-currency-bundle
A Symfony bundle for working with currencies: manage currency definitions, handle exchange rates, format and convert monetary amounts, and integrate currency data into your applications through reusable services and Twig helpers.
Because this bundle was last released in January 2017 and has no dependents or stars, treat it as an unmaintained artifact you are adapting rather than a package you are adopting. Start by cloning the repo locally and reading composer.json, DependencyInjection/, and Resources/config/ before attempting an install.
1. Inspect before installing
git clone https://github.com/pigroupe/SfynxCurrencyBundle
cd SfynxCurrencyBundle
cat composer.json # check symfony/* constraints
ls DependencyInjection/ # find the extension and its config tree
ls Resources/config/ # services.yml is where the service IDs live
The composer.json will tell you which Symfony major version this targets (almost certainly 2.8/3.x). If you are on Symfony 4+, expect to rewrite the bundle registration by hand.
2. Register the bundle
Symfony 3 and earlier — add to app/AppKernel.php:
public function registerBundles()
{
$bundles = [
// ...
new Sfynx\CurrencyBundle\SfynxCurrencyBundle(),
];
}
Symfony 4+ — add to config/bundles.php:
return [
// ...
Sfynx\CurrencyBundle\SfynxCurrencyBundle::class => ['all' => true],
];
If it fails to autoload under PSR-4, check the autoload block in its composer.json; older Sfynx bundles sometimes used PSR-0 with a Sfynx\Bundle\ namespace you'll need to alias.
3. Publish and read the config
php bin/console config:dump-reference sfynx_currency
The extension alias is the single most useful thing to know. It surfaces every option the bundle exposes — base currency, providers, cache TTL, rounding mode. Copy the defaults into config/packages/sfynx_currency.yaml and adjust only the base currency first.
4. First use case: convert a price
The realistic entry point is currency conversion at display time. Assume a service such as sfynx.currency.manager (verify against Resources/config/services.yml). Fetch it in a controller and convert a stored amount:
$manager = $this->get('sfynx.currency.manager');
$converted = $manager->convert(99.00, 'EUR', 'USD');
If that throws, the service is likely named differently — grep the config file for class: entries that implement a converter or calculator interface. That interface is your real API.
Wrap the service, don't leak it. The bundle's service IDs are unstable (they may change if you fork it to fix Symfony 5+ compatibility). Define your own thin interface in your app and bind the bundle service to it:
services:
App\Currency\Converter:
arguments: ['@sfynx.currency.manager']
Then inject App\Currency\Converter everywhere. When the bundle inevitably needs patching, you change one line.
Use it at the template boundary, not in your domain. Currency conversion is a presentation concern. Instead of storing converted values, expose a Twig filter or function that reads from your wrapper:
class CurrencyExtension extends \Twig_Extension
{
public function getFilters()
{
return [new \Twig_SimpleFilter('currency', [$this, 'convert'])];
}
public function convert($amount, $from, $to)
{
return $this->converter->convert($amount, $from, $to);
}
}
This keeps the bundle's lifecycle decoupled from your entities and migrations.
Cache aggressively at your layer. A 2017 bundle will almost certainly hit an external exchange-rate API synchronously. Put a Symfony cache adapter in front of your wrapper so a page rendering 200 product prices doesn't make 200 HTTP calls:
public function convert($amount, $from, $to)
{
$key = sprintf('rate_%s_%s', $from, $to);
if (null === $rate = $this->cache->getItem($key)->get()) {
$rate = $this->inner->getRate($from, $to);
$item = $this->cache->getItem($key);
$item->set($rate)->expiresAfter(3600);
$this->cache->save($item);
}
return $amount * $rate;
}
Batch conversions. If the bundle exposes only a single-pair API, collect all (from, to) pairs from a request, resolve rates once, and multiply per item. This is the pattern that scales in cart and catalogue views.
Keep the provider pluggable. If the bundle defines an exchange-rate provider interface, register your own implementation. That lets you swap the 2017-era default (which may call a dead endpoint) for a current service without touching bundle internals.
Integration tip: form types. For a currency selector, prefer Symfony's CurrencyType (which ships with the framework) for the input widget and use this bundle only for the actual rate lookup. Don't couple your form system to an unmaintained bundle.
License is NOASSERTION — this is a blocker for commercial use until resolved. Check the repo for a LICENSE file. If there isn't one, the code is effectively "all rights reserved" in many jurisdictions. Get written clarification from the maintainer or choose an alternative before shipping to production. This is the single most important item in this assessment.
Symfony compatibility is the main integration cost. A 2017 release predates Symfony 4's bundle auto-registration, Flex recipes, and the AbstractController change. Expect to:
type: "symfony-bundle" handling manuallyservices.yml if it uses deprecated scope: or synchronized: service attributes$this->get() with constructor injection (the bundle may still register container-aware services)symfony/* constraints in your own composer.json with a replace or forkForking to a local vendor/ path via a Composer repositories entry is the least painful route:
"repositories": [
{ "type": "vcs", "url": "https://github.com/your-org/SfynxCurrencyBundle" }
]
The service IDs are undocumented. There's no star count, no docs site, and no dependents, so there's no community knowledge to lean on. Run php bin/console debug:container --tag=... or simply grep -r "sfynx.currency" vendor/ to map the IDs yourself. Do this once and write it down — you'll otherwise redo it every few months.
Exchange rates can be stale or wrong silently. If the bundle ships a default provider, verify it actually reaches a live endpoint. A 2017 API URL is likely dead or rate-limited. Add a health check (a console command that calls getRate for a known pair and asserts a plausible range) and run it on deploy.
Rounding is a classic pitfall. Currency conversion that returns floats and relies on round() produces off-by-one-cent errors in totals. If the bundle exposes a rounding mode config, set it explicitly (e.g. half-up on totals, half-even on line items). Otherwise round in your wrapper and never let raw floats reach an invoice.
Zero-rate and missing-pair handling. Most currency services throw on unknown pairs; catch and fall back to a stored manual rate rather than rendering a broken price. Log the miss with the pair so you can pre-warm the cache.
Extension points worth patching in a fork. In priority order:
ClockInterface or injectable "now" so TTL tests are deterministic.getRates(array $pairs) method to reduce API calls.date()/time() calls — common in 2017-era bundles and a frequent source of flaky tests.Debugging checklist when a conversion returns the wrong value:
debug:container sfynx.currency.manager — confirm you injected what you thinkfrom argument you're passingUSD_EUR vs EUR_USD)Alternatives, honestly. For new work, moneyphp/money plus florianv/swap (or exchanger) gives you an actively maintained, well-typed stack with a Symfony-friendly architecture. Reach for this bundle only if you are maintaining an existing Sfynx-based system and want to keep its conventions — not as a greenfield choice.
How can I help you explore Laravel packages today?