brightcreations/money-converter
Composer 安装命令:
composer require brightcreations/money-converter
包简介
A Laravel package for converting currencies using exchange rates.
README 文档
README
A Laravel package for converting money between currencies using stored exchange rates and Brick Money.
Overview
brightcreations/money-converter converts amounts between currencies in minor units (cents). It reads rates from your database (populated by brightcreations/exchange-rates) and supports current, fresh, historical, interpolated, and extrapolated conversions.
Requirements
| Dependency | Version |
|---|---|
| PHP | >=8.1 |
| Laravel | 10, 11, or 12 (database component) |
| brightcreations/exchange-rates | ^0.9.0 |
Installation
composer require brightcreations/money-converter brightcreations/exchange-rates
Both packages auto-register their service providers.
Integration guide
Follow these steps to go from zero to a working conversion.
1. Publish exchange-rates config and migrations
php artisan vendor:publish --tag=exchange-rates-config php artisan vendor:publish --tag=exchange-rate-migrations php artisan migrate
2. Configure exchange-rate API keys
Add provider credentials to .env. See the exchange-rates installation guide for full details.
EXCHANGE_RATE_API_TOKEN=your_token OPEN_EXCHANGE_RATE_APP_ID=your_app_id
3. Publish money-converter config
php artisan vendor:publish --tag=money-converter-config
4. Populate exchange rates
Load rates into the database using either approach:
# Historical backfill (recommended for World Bank or DB-only workflows)
php artisan exchange-rates:backfill
// Or fetch current rates for a base currency use BrightCreations\ExchangeRates\Facades\ExchangeRate; ExchangeRate::storeExchangeRates('USD');
5. Convert
use BrightCreations\MoneyConverter\Contracts\MoneyConverterInterface; $convertedMinor = app(MoneyConverterInterface::class)->convert(10000, 'USD', 'EUR'); // 10000 USD cents (100.00 USD) → EUR cents
Configuration
Published to config/money-converter.php.
| Key | Default | Description |
|---|---|---|
default_provider |
PDO builder | Brick ExchangeRateProvider used for current/fresh conversion (ExchangeRateProvidersEnum::PDO) |
proxy_currency_code |
USD |
Base currency for historical proxy cross-rates when a direct pair is missing |
rounding_mode |
RoundingMode::DOWN |
Brick rounding when converting to minor units |
exchange_rates.pdo.table |
currency_exchange_rates |
Same table written by exchange-rates |
exchange_rates.pdo.column |
exchange_rate |
Rate column |
exchange_rates.pdo.source_currency_column |
base_currency_code |
Source currency column |
exchange_rates.pdo.target_currency_column |
target_currency_code |
Target currency column |
exchange_rates.configurable.rates |
see config file | Base → target rate map for local dev (no DB) |
Environment overrides: EXCHANGE_RATE_DB_TABLE, EXCHANGE_RATE_DB_COLUMN, EXCHANGE_RATE_DB_SOURCE_CURRENCY_COLUMN, EXCHANGE_RATE_DB_TARGET_CURRENCY_COLUMN.
PDO column names must match the exchange-rates schema.
Local development without a database
Set default_provider to the configurable builder class so Brick reads static rates from config:
use BrightCreations\MoneyConverter\Enums\ExchangeRateProvidersEnum; 'default_provider' => ExchangeRateProvidersEnum::CONFIGURABLE->value,
Edit exchange_rates.configurable.rates in config/money-converter.php to add or change pairs. This provider is intended for local/testing only; production should use PDO with exchange-rates populated data.
Usage
Minor units
All amounts are in minor units (cents, pence, etc.):
| Input | Meaning |
|---|---|
10000 with USD |
100.00 USD |
5000 with EUR |
50.00 EUR |
Same-currency conversion returns the input unchanged.
Basic conversion
use BrightCreations\MoneyConverter\Contracts\MoneyConverterInterface; $service = app(MoneyConverterInterface::class); // Current rate (from database via PDO provider) $eurCents = $service->convert(10000, 'USD', 'EUR'); // Historical rate (pass a date; use startOfDay() for predictable date-only matching) $eurCents = $service->convert(10000, 'USD', 'EUR', now()->subDays(7)->startOfDay());
Resolving the service
Constructor injection
use BrightCreations\MoneyConverter\Contracts\MoneyConverterInterface; class InvoiceService { public function __construct( private MoneyConverterInterface $moneyConverter ) {} public function convertTotal(int $amountCents, string $from, string $to): int { return $this->moneyConverter->convert($amountCents, $from, $to); } }
Container
$service = resolve(MoneyConverterInterface::class); // or $service = app()->make(MoneyConverterInterface::class);
Facade
use BrightCreations\MoneyConverter\Facades\MoneyConverter; $eurCents = MoneyConverter::convert(10000, 'USD', 'EUR'); // Fluent options (see API reference) $eurCents = MoneyConverter::fetchOnFail() ->interpolate() ->convertHistorical(10000, 'USD', 'EUR', now()->subDays(30)->startOfDay());
Note:
MoneyConverteris registered as a singleton, but fluent methods (fetchOnFail(),extrapolate(),interpolate(), etc.) return a new configured instance and do not mutate the shared singleton. The optional$on_failargument onconvert()is also scoped to that call only.
API reference
Conversion methods
| Method | Description |
|---|---|
convert($money, $from, $to, $dateTime = null, $onFail = null, $options = null) |
Routes to current, fresh, or historical conversion based on date and flags |
convertCurrent($money, $from, $to, $options = null) |
Uses rates in the database (PDO provider) |
convertFresh($money, $from, $to, $options = null) |
Fetches fresh rates via exchange-rates, then converts |
convertToday($money, $from, $to, $options = null) |
Historical conversion at today's startOfDay() |
convertHistorical($money, $from, $to, $dateTime, $options = null) |
Historical fallback chain (see below) |
convertWithResult($money, $from, $to, $dateTime = null, $onFail = null, $options = null) |
Same routing as convert() but returns MoneyConversionResult (amount, rate, strategy, provider) |
convertBulk(ConversionItem[] $items, $options = null) |
Batch conversion; returns int[] in input order |
convertBulkWithResult(ConversionItem[] $items, $options = null) |
Batch conversion with metadata per item |
ConversionItem accepts amount, from, to, and optional date for historical rows.
Fluent methods
| Method | Description |
|---|---|
extrapolate(bool $enable = true) |
Nearest-neighbour rate when target is outside stored date range; returns a new instance |
interpolate(bool $enable = true) |
Linear interpolation between two bounding historical rates; returns a new instance |
needsFresh(bool $enable = true) |
Route convert() without a date through convertFresh(); returns a new instance |
throwOnFail() |
Throw on conversion failure (default); returns a new instance |
fetchOnFail() |
Fetch rates from API on failure where the provider supports it; returns a new instance |
isThrowOnFail() / isFetchOnFail() |
Inspect current failure mode |
withOptions(MoneyConverterOptions $options) |
Return a new instance with the given options object |
Options object
For explicit per-call configuration without a fluent chain, pass a MoneyConverterOptions instance:
use BrightCreations\MoneyConverter\DTOs\MoneyConverterOptions; $opts = MoneyConverterOptions::defaults() ->withFetchOnFail() ->withInterpolate(); $result = $service->convertWithResult(10000, 'USD', 'EUR', $date, options: $opts); $amounts = $service->convertBulk($items, $opts); $amount = $service->convertHistorical(10000, 'USD', 'EUR', $date, $opts);
Set application-wide defaults in config/money-converter.php:
'default_options' => [ 'extrapolate' => false, 'interpolate' => false, 'needs_fresh' => false, 'on_fail' => 'throw', // or 'fetch' ],
MoneyConverter reads these when resolved from the container. Per-call $options or fluent methods override them.
Precedence for convert() / convertWithResult():
- Explicit
$on_failargument (when non-null) overridesoptions->onFailfor that call $optionsargument (when non-null) overrides instance options- Instance options from fluent methods or
withOptions() - Config
default_options(constructor baseline)
Audit events
After each successful conversion, the package dispatches BrightCreations\MoneyConverter\Events\ConversionPerformed (one event per bulk item). Listeners are registered from config/money-converter.php; the default includes LogConversionPerformed, which writes an info log with input/output amounts, currencies, rate, strategy, and provider.
Disable event dispatch via .env:
MONEY_CONVERTER_DISPATCH_CONVERSION_EVENTS=false
Configure listeners in config/money-converter.php (remove LogConversionPerformed to turn off package logging, or add your own):
use BrightCreations\MoneyConverter\Listeners\LogConversionPerformed; 'events' => [ 'listeners' => [ LogConversionPerformed::class, \App\Listeners\PersistConversionAudit::class, ], ],
Or in your app's EventServiceProvider:
protected $listen = [ \BrightCreations\MoneyConverter\Events\ConversionPerformed::class => [ \App\Listeners\PersistConversionAudit::class, ], ];
Constants
| Constant | Value | Meaning |
|---|---|---|
ON_FAIL_THROW_EXCEPTION |
1 |
Throw MoneyConversionException on failure |
ON_FAIL_FETCH_EXCHANGE_RATES |
2 |
Attempt to fetch rates before failing |
Pass as the fifth argument to convert() to temporarily set failure mode:
$service->convert(10000, 'USD', 'EUR', null, MoneyConverterInterface::ON_FAIL_FETCH_EXCHANGE_RATES);
Historical conversion
Historical conversion runs a fallback chain: exact DB lookup → optional API fetch (fetchOnFail()) → proxy-currency cross-rate → optional interpolate() → optional extrapolate().
Datetime semantics
- Exact lookup (step 1) matches by date only (
whereDate), not time. PassstartOfDay()for predictable results. convertToday()already usesstartOfDay().- Bounding, interpolation, and extrapolation use full datetime (
<=/>=ondate_time).
fetchOnFail() and providers
When fetchOnFail() is set, historical conversion attempts an API fetch after a DB miss. Behaviour depends on your exchange-rates provider:
| Provider | Auto-fetch on historical miss | Granularity |
|---|---|---|
| Open Exchange Rates | Yes | Daily |
| Exchange Rate API | Yes | Daily |
| World Bank | No (DB only) | Yearly |
For World Bank or DB-only setups, run php artisan exchange-rates:backfill to populate historical data.
interpolate() and extrapolate()
use Carbon\Carbon; // Fill a gap between two stored dates (linear interpolation) $service->interpolate()->convertHistorical(10000, 'USD', 'EUR', Carbon::parse('2024-01-08')); // Target after latest stored rate (nearest previous rate) $service->extrapolate()->convertHistorical(10000, 'USD', 'EUR', Carbon::parse('2024-06-01')); // Target before earliest stored rate (nearest next rate) $service->extrapolate()->convertHistorical(10000, 'USD', 'EUR', Carbon::parse('2024-01-01'));
interpolate()— uses two bounding rates when the target falls strictly between stored dates.extrapolate()— uses the nearest single stored rate when the target is before the earliest or after the latest available date.
Exceptions
| Exception | When |
|---|---|
MoneyConversionException |
Conversion fails after all strategies are exhausted, or a non-recoverable error occurs in a convert method |
InvalidArgumentException |
Invalid $on_fail value passed to convert() (must be ON_FAIL_THROW_EXCEPTION or ON_FAIL_FETCH_EXCHANGE_RATES) |
MoneyConversionException wraps the underlying cause when applicable (e.g. missing rate, unsupported historical provider).
Rate sourcing
money-converter does not fetch exchange rates on its own for day-to-day storage — that is handled by brightcreations/exchange-rates. Install and configure exchange-rates to populate currency_exchange_rates and currency_exchange_rates_history, then use money-converter to convert.
Contributing
Contributions are welcome. Please open an issue or pull request on GitHub.
License
MIT License. See LICENSE.
Author
Kareem Mohamed — Bright Creations
brightcreations/money-converter 适用场景与选型建议
brightcreations/money-converter 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 8.55k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2025 年 05 月 22 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「currency conversion」 「laravel」 「exchange rates」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 brightcreations/money-converter 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 brightcreations/money-converter 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 brightcreations/money-converter 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
A library that provides a simple infrastructure to create your own converters and to perform any conversion you want
Fixer.io data provider for Peso
TCMB Currenct Converter
Color conversion library
Convert and serve jpeg/png to webp with PHP (if at all possible)
Serve autogenerated WebP images instead of jpeg/png to browsers that supports WebP
统计信息
- 总下载量: 8.55k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 21
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-05-22