florianv/laravel-swap
Laravel Swap lets you convert currencies and fetch exchange rates in Laravel apps. It wraps the Swap PHP library, supporting multiple rate providers, caching, and simple configuration for reliable currency conversion.
Architecture fit. florianv/laravel-swap remains a thin Laravel integration layer over the mature florianv/swap currency-exchange library. It contributes three things: an auto-discovered service provider (container bindings), a facade (Swap::), and a publishable config file. That is a good architectural fit for Laravel applications that need point-in-time currency conversion — pricing display, invoicing, reporting, multi-currency checkout — without building their own provider abstraction. It is explicitly not an FX treasury, rate-ledger, or historical time-series store; those concerns remain application-owned. 2.5.0 does not change this positioning, but it does tighten the framework floor (Laravel 11+) and harden configuration validation, which reinforces the "convenience binding, not platform dependency" framing. Assess it as a convenience binding with a now-narrower supported platform window.
Integration feasibility. High for Laravel 11/12/13 estates; blocked for anyone still on Laravel 10 or Lumen. One composer require, zero manual provider registration (Laravel auto-discovery), php artisan vendor:publish for config, and provider credentials via .env. Time-to-first-conversion is measured in minutes. 2.5.0 materially improves the failure surface here: non-name values for swap.cache, swap.http_client, and swap.request_factory now throw a clear InvalidArgumentException instead of failing obscurely, and the provider config option names are corrected (api_key rather than access_key for the APILayer services). The real integration work remains policy, not plumbing: rounding rules, base-currency convention, and cache TTLs all live in your code, not the package.
Technical risk. Moderate, with the balance shifting:
config/swap.php will carry the stale access_key names for APILayer-backed providers. Upgrades will not fix existing published config — re-publish or patch it deliberately, and verify auth succeeds per provider post-upgrade.exchange_rates_api free plan is EUR-based, and coin_layer transmits the key over plain HTTP unless paid is true — the latter is a security-review item if we ever enable it.CONTRIBUTING.md including an AI-assisted contributions policy, docs-sync test against Exchanger). That raises confidence in the maintainer's process without changing the structural single-maintainer risk. Still requires an internal owner and version pinning.Key questions for the team.
api_key names?coin_layer ever in scope? If so, does the paid => true requirement satisfy security review?Stack fit. Assumes a conventional Laravel 11/12/13 application (service provider + facade idiom) on a supported PHP version. It is framework-idiomatic and payment-processor-agnostic — it composes cleanly with any checkout, billing, or catalog system. If the codebase is not Laravel, or is still on Laravel 10/Lumen, this package adds no value over using florianv/swap directly — and on Laravel 10 the new version won't install at all.
Migration path. Do not call the facade directly from domain code. Introduce a narrow internal interface (e.g. CurrencyConverter) with a SwapCurrencyConverter implementation bound in a service provider. This:
Legacy hardcoded-rate call sites can then be migrated incrementally behind that interface rather than in a big-bang rewrite.
Compatibility checks before committing.
florianv/swap ^4.6 / Exchanger 2.11 — confirm this resolves against our existing lockfile and doesn't force transitive bumps (Guzzle/HTTP client, psr/simple-cache).config/swap.php against the 2.5.0 stub; specifically reconcile access_key → api_key for APILayer providers and confirm no removed keys are still referenced.InvalidArgumentException at boot.Sequencing.
CurrencyConverter interface, rounding rules, and base-currency convention before any business feature uses it (do this concurrently if it isn't already in place — it is the reason this upgrade is low-risk).Maintenance. Small dependency surface and low churn expected from the Laravel wrapper itself. 2.5.0 raises the baseline hygiene bar considerably — php-cs-fixer, hardened CI, Psalm 7 without a baseline, Shepherd type coverage, and a test that keeps provider docs in sync with Exchanger — which lowers our review cost per upgrade. But the maintenance burden still sits with (a) the upstream swap library, (b) provider API changes, and (c) our own config and cache tuning. The Laravel-version drop is a signal: this package tracks framework EOL, so our framework upgrade cadence now dictates our ability to take security and provider fixes. Pin exact versions, subscribe to advisory feeds, schedule a quarterly dependency review, and add "framework floor moved" to the standing agenda. Budget a named internal owner.
Support. No commercial support tier; community/MIT only. Support model must be internal: a runbook covering provider outage, key rotation, rate anomaly response, and fallback verification. Two new runbook entries from 2.5.0: (i) config validation failures at boot (InvalidArgumentException on cache/HTTP-client/request-factory) and (ii) provider auth failures traced to stale access_key config post-upgrade. On-call should know that "wrong price displayed" is a first-class incident class, not a cosmetic bug.
Scaling. The package is stateless from our perspective — scaling is almost entirely a caching and quota problem. Rate calls are external network I/O; without aggressive caching, throughput is bounded by provider quotas, not by our infrastructure. Design for cache-first reads, per-pair cache keys, and a pre-warm strategy for high-traffic pairs. Redis sizing and eviction policy matter more than application replicas. 2.5.0's requirement that cache be named rather than injected is mildly helpful here: it makes the cache topology explicit and reviewable rather than an incidental object graph.
Failure modes to design for.
exchange_rates_api EUR-base behavior when writing those bounds.Ramp-up. A Laravel developer can be productive in under an hour. A responsible integration — abstraction, caching, rounding tests, observability, audit persistence, and failover drills — is roughly one to two sprints for a small team. The 2.5.0 upgrade itself is a small, well-documented piece of work (config diff plus a boot check); the cost sits in the framework-floor triage for Laravel 10 services, and the learning curve remains in the FX domain policy the package deliberately does not own.
How can I help you explore Laravel packages today?