flagbit/currency-bundle
Flagbit CurrencyBundle is a PHP/Symfony bundle for handling currencies and exchange rates. It provides services for currency conversion, formatting, and managing currency data, helping applications display and calculate monetary values reliably across multiple currencies.
Architecture fit — poor, and the framing mismatch is the headline finding. Despite being indexed as a "Laravel/PHP package," flagbit/currency-bundle is a Symfony FrameworkBundle. Its entry point is a Bundle subclass registered in AppKernel, its configuration flows through a DependencyInjection\Extension + Configuration tree, and its services are wired via compiler passes and XML/YAML service definitions. Laravel has no bundle registry, no Extension/Configuration contract, and no compiler-pass lifecycle. The only overlap is the PSR-11 container boundary, which is not enough to make the package loadable. In a Laravel application this package is effectively inert code: installing it adds a vendor directory and nothing else executes.
Integration feasibility — low, and the cost is a port, not an integration. Making it useful requires translating the bundle into Laravel idioms: Extension → ServiceProvider, config tree → config/currency.php, service definitions → container bindings/singletons, Symfony event subscribers → Laravel listeners. That is not a configuration exercise; it is a rewrite with the original source as a reference spec. The effort is only justified if the underlying domain logic (currency entity, exchange-rate retrieval, conversion arithmetic) is both non-trivial and cleanly separable from Symfony wiring — which cannot be assumed for a bundle of this vintage.
Technical risk — high, concentrated in the dependency graph. Three signals compound:
The practical failure is likely to arrive early: bundles of this era pin symfony/* to ^2/^3 and PHP to 5.x/7.x, which will hard-conflict with Laravel 10/11 (Symfony 6/7, PHP 8.1+). Expect composer require to fail on resolution, not to succeed and misbehave — a cheaper failure, but a failure.
Key questions for discovery:
float or decimal? Float currency storage is a correctness defect we would inherit.moneyphp/money, brick/money) that covers the same ground with an active maintainer?Verdict: reject for direct adoption. The package fails on stack fit before it fails on maintenance, and it fails on maintenance before it fails on quality. Retain as a reference implementation to be read during discovery, not a dependency.
Stack fit — none, by construction. Laravel's currency needs are met by framework-agnostic value objects plus a Laravel-native service provider. This package cannot occupy that slot without being rewritten into it. The correct mental model is: we are not integrating a package, we are deciding whether to port one.
Migration path. The only coherent path is an extraction-and-replace:
composer.json entirely.ExchangeRateProvider and CurrencyConverter as interfaces bound in a CurrencyServiceProvider; rates behind a cache repository with a scheduled RefreshExchangeRates command; decimal-typed storage.moneyphp/money or brick/money for value objects and rounding; our own provider for rates. This is where the real durability comes from — the FX plumbing is commodity, the bundle was never the differentiator.Compatibility. Assume incompatibility until disproven, and disprove it cheaply before any design work: clone the repo, run composer why-not laravel/framework, and check the composer.json PHP and symfony/* constraints. If the constraints are Symfony 2/3-era, stop — the investigation is over. There is no shim, no polyfill, and no maintained fork.
Sequencing:
moneyphp/money + in-house provider. The archived package should have to win this comparison, which it will not on maintenance grounds alone.ExchangeRateProvider / CurrencyConverter in our domain before any implementation, so the vendor choice stays reversible.Where a legacy Symfony estate is involved: if we are migrating from a Symfony app that already runs this bundle, the bundle is a migration liability, not an asset. Port the behavior, do not lift the code. The rewrite cost is paid either way, and paying it once — into a maintained library — is the only version that does not recur at the next PHP upgrade.
Maintenance — the dominant cost, and it is unbounded. Archived means zero upstream maintenance, transferred entirely to us. Every future PHP minor, every Symfony/Laravel major, every CVE in a transitive dependency becomes our ticket. A fork-and-own arrangement is viable only for a small, stable, dependency-light codebase; a Symfony bundle from this era is unlikely to be any of those. Budget the ongoing cost as we now maintain a currency library, and ask whether that is a capability the team should own.
Support — effectively absent. 0 stars, 0 dependents, archived: there is no issue tracker with activity, no maintainer to escalate to, no community surface to search. Every defect is diagnosed by reading source. For a payments-adjacent capability, that is a poor support posture, and it will surface as extended MTTR during an incident rather than as a line item.
Scaling — the rate-refresh path is the pressure point, not request volume. Currency conversion itself is cheap arithmetic; the scaling risk is external FX provider calls. Requirements regardless of implementation: cache rates with an explicit TTL, refresh on a schedule rather than per-request, rate-limit and retry against the provider with backoff, and hold a durable last-known-good snapshot. If the bundle fetches rates synchronously per request, it will not survive production traffic and will couple checkout latency to a third party's availability. Verify this in discovery — it is the single most likely operational defect.
Failure modes to design against:
composer update with no upstream fix path.Ramp-up — deceptive. For an engineer fluent in Symfony, the code is readable in hours; for a Laravel team with no Symfony bundle experience, the wiring is unfamiliar and the payoff is a port. Either way the onboarding cost is "read the source and reverse-engineer intent," with no documentation to anchor against. That cost is paid and then stranded, because the knowledge is specific to code we intend to replace.
Bottom line for planning: treat this as a build-vs-buy input, not an adoption candidate. The scanner score of 0.05 is the correct read. Recommend a one-day discovery to extract any genuinely reusable domain logic, then implement the capability on a maintained, framework-agnostic foundation behind Laravel-native interfaces. The archived bundle has no path to production in a Laravel stack that does not begin with rewriting it.
How can I help you explore Laravel packages today?