moneyphp/iso-currencies
Provides an up-to-date ISO 4217 currency list sourced from the official ISO Maintenance Agency (currency-iso.org). Designed primarily for moneyphp/money, with composer commands to install and fetch updates for currency data.
Install the Package Add the package to your Laravel project via Composer:
composer require moneyphp/iso-currencies
For Laravel, also install the optional moneyphp/money package if not already present:
composer require moneyphp/money
Update Currencies Fetch the latest ISO 4217 currency data (including historical flags like BGN):
composer fetch-update
This updates the static currency dataset from the ISO Maintenance Agency.
First Use Case: Validate a Currency
Use the CurrencyRepository to check if a currency code is valid and its status (active/historic):
use Money\Currency\CurrencyRepository;
use Money\Currency\ISO4217;
$repository = new CurrencyRepository();
$currency = $repository->getCurrency('EUR'); // Returns ISO4217 object
$isValid = $repository->exists('EUR'); // true
$isHistoric = $repository->getCurrency('BGN')->isHistoric(); // true (post-2026)
Laravel Integration (Optional)
Bind the CurrencyRepository to Laravel’s service container in AppServiceProvider:
use Illuminate\Support\ServiceProvider;
use Money\Currency\CurrencyRepository;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(CurrencyRepository::class, function () {
return new CurrencyRepository();
});
}
}
Now inject CurrencyRepository into controllers/services:
use Money\Currency\CurrencyRepository;
class PaymentController
{
public function __construct(private CurrencyRepository $currencyRepo) {}
public function process()
{
if (!$this->currencyRepo->exists('XXX')) {
abort(400, 'Invalid currency');
}
}
}
Currency Validation Validate user input (e.g., API requests, forms) against ISO 4217 standards:
$repository = app(CurrencyRepository::class);
$currencyCode = request('currency');
if (!$repository->exists($currencyCode)) {
return response()->json(['error' => 'Invalid currency'], 400);
}
// Check for historical currencies (e.g., BGN post-2026)
$currency = $repository->getCurrency($currencyCode);
if ($currency->isHistoric()) {
logger()->warning("Using historic currency: {$currencyCode}");
}
Dynamic Currency Selection Fetch all active currencies for dropdowns or reporting:
$activeCurrencies = $repository->getAll()->filter(fn ($c) => !$c->isHistoric());
return view('pricing', ['currencies' => $activeCurrencies]);
Integration with moneyphp/money
Use the repository to create Money objects with validated currencies:
use Money\Money;
use Money\Currency\Currency;
$amount = Money::EUR(100); // Throws exception if currency is invalid/historic
$currency = $repository->getCurrency('EUR');
$money = new Money(100, $currency);
Historical Currency Handling Flag or reject transactions using deprecated currencies (e.g., BGN after 2026):
$transactionCurrency = 'BGN';
$now = new DateTime();
$effectiveDate = new DateTime('2026-01-01');
if ($repository->getCurrency($transactionCurrency)->isHistoric() &&
$now >= $effectiveDate) {
throw new \RuntimeException("Currency {$transactionCurrency} is no longer valid");
}
Service Binding
Extend the base CurrencyRepository to add Laravel-specific features (e.g., caching):
namespace App\Services;
use Money\Currency\CurrencyRepository as BaseRepository;
use Illuminate\Support\Facades\Cache;
class CurrencyRepository extends BaseRepository
{
public function getCurrency(string $code)
{
return Cache::remember("currency.{$code}", now()->addHours(1), function () {
return parent::getCurrency($code);
});
}
}
Rebind in AppServiceProvider:
$this->app->singleton(CurrencyRepository::class, function () {
return new App\Services\CurrencyRepository();
});
Form Request Validation Use the repository in Laravel’s form requests:
use Illuminate\Validation\Rule;
use Money\Currency\CurrencyRepository;
class StorePaymentRequest extends FormRequest
{
public function rules()
{
return [
'currency' => [
'required',
Rule::exists('currency_repository', 'code')->where(function ($query) {
$query->where('is_historic', false);
}),
],
];
}
public function withValidator($validator)
{
$validator->after(function ($validator) {
$repository = app(CurrencyRepository::class);
if ($repository->getCurrency($this->currency)->isHistoric()) {
$validator->errors()->add('currency', 'Historical currency not allowed');
}
});
}
}
API Responses Return standardized currency data in APIs:
Route::get('/currencies', function () {
$repository = app(CurrencyRepository::class);
return response()->json([
'data' => $repository->getAll()->map(function ($currency) {
return [
'code' => $currency->getCode(),
'name' => $currency->getName(),
'symbol' => $currency->getSymbol(),
'is_historic' => $currency->isHistoric(),
];
}),
]);
});
Migration Helper Use the package to validate currency fields in database migrations:
use Money\Currency\CurrencyRepository;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePaymentsTable extends Migration
{
public function up()
{
$repository = app(CurrencyRepository::class);
$validCodes = $repository->getAll()->pluck('code')->all();
Schema::create('payments', function (Blueprint $table) use ($validCodes) {
$table->string('currency')->required();
$table->foreign('currency')
->references('code')
->on('currencies')
->whereIn('code', $validCodes);
});
}
}
Historical Currency Logic
isHistoric() flag is not time-aware by default. For example, BGN is marked as historic, but you may need to check if a transaction occurred before the deprecation date (2026-01-01).$currency = $repository->getCurrency('BGN');
$transactionDate = new DateTime('2025-12-31');
$effectiveDate = new DateTime('2026-01-01');
if ($currency->isHistoric() && $transactionDate >= $effectiveDate) {
throw new \RuntimeException("Currency {$currency->getCode()} is invalid for transactions on or after {$effectiveDate->format('Y-m-d')}");
}
Composer Update Quirks
composer fetch-update overwrites the local currency data. If you’ve customized the data (e.g., added internal currencies), these changes will be lost.resources/currencies directory. For custom currencies, extend the repository:
class ExtendedCurrencyRepository extends CurrencyRepository
{
protected function getCurrencies(): array
{
$currencies = parent::getCurrencies();
$currencies['INTERNAL'] = new ISO4217('INTERNAL', 'Internal Units', 'IU', 2);
return $currencies;
}
}
PHP Version Constraints
3.4.0 for PHP 8.0).composer.json for PHP requirements and pin the version:
"require": {
"moneyphp/iso-currencies": "3.4.0"
}
Caching Static Data
How can I help you explore Laravel packages today?