PHPackages                             mistralys/currency-parser - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Parsing &amp; Serialization](/categories/parsing)
4. /
5. mistralys/currency-parser

ActiveLibrary[Parsing &amp; Serialization](/categories/parsing)

mistralys/currency-parser
=========================

PHP library that can detect prices written in text or markup, and normalise their formatting according to country-specific rules.

1.1.1(11mo ago)34.7k↓50%2[1 issues](https://github.com/Mistralys/currency-parser/issues)MITPHPPHP ^7.4|^8.0

Since Feb 22Pushed 11mo ago1 watchersCompare

[ Source](https://github.com/Mistralys/currency-parser)[ Packagist](https://packagist.org/packages/mistralys/currency-parser)[ RSS](/packages/mistralys-currency-parser/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (6)Versions (16)Used By (0)

Currency parser
===============

[](#currency-parser)

PHP library that can detect prices written in text or markup, adding non-breaking spaces, and normalising their formatting according to country-specific rules.

Requirements
------------

[](#requirements)

- PHP 7.4+
- [Composer](https://getcomposer.org)

Installation
------------

[](#installation)

Use Composer to add the library to your project:

```
composer require mistralys/currency-parser

```

Alternatively, clone it locally using the GIT command line (or [GitHub Desktop](https://desktop.github.com/)), or manually [download a release](https://github.com/Mistralys/currency-parser/releases).

Examples of recognized formats
------------------------------

[](#examples-of-recognized-formats)

Primarily intended to parse prices written by humans, the parser is quite tolerant and will recognize any of these notations (and more) - either as standalone text or scattered in a larger document.

- `$1000`
- `$1,000.00` *With thousands separators*
- `$ 1 , 000 . 00` *Free-spacing, including newlines*
- `$1.000,00` *Separator style agnostic*
- `$1.000.00` *Same separator mistake\**
- `$1000.2` *1 to 2 decimal places*
- `1000 EUR` *Currency symbols or names*
- `EUR 1000` *Symbol placement agnostic*
- `-$ 1000` *Minus before symbol*
- `$ -1000` *Minus after symbol*
- `50,- €` *German short style decimals*
- `1 000,00 € TTC` *French style with VAT*
- `.50 €` *Decimals only*

> - Based on the assumption that prices always have 1-2 decimal places, this part of the number is assumed to be the decimals.

### *Euro* exception

[](#euro-exception)

The *Euro* is the only one of the supported currencies whose name begins with the same letters as its currency name, `EUR`. The parser will ignore prices written like this:

```
"...and he gave him 42 Euro for his troubles."

```

The reasoning being that using this name is ambiguous in a pure currency context. It is typically used when mentioning prices in body text, where price formatting is not necessary or even expected.

Quick Start
-----------

[](#quick-start)

### Get a list of prices in a text or markup

[](#get-a-list-of-prices-in-a-text-or-markup)

```
use function Mistralys\CurrencyParser\findPrices;

$subject = formatText();
```

Output:

```
$1,000.00

```

With a specific currency locale for precise formatting when the currency is used in several countries, like the Euro:

```
use function Mistralys\CurrencyParser\parsePrice;

echo parsePrice('1000.00 €', 'EUR_DE')->formatText();
```

Output:

```
1.000,00 €

```

### Format all prices in a text or markup

[](#format-all-prices-in-a-text-or-markup)

The following will automatically format prices according to the selected currencies' default locale.

```
use Mistralys\CurrencyParser\PriceFilter;

$subject = filterString($subject);
```

Output:

```
Starting price: $1,000.00
Special price: 860.00 €

```

To be more precise, the currency locale can be provided. For example, Euros are formatted slightly differently in France than in the rest of Europe.

```
use Mistralys\CurrencyParser\PriceFilter;

$subject = filterString($subject);
```

Output:

```
Prix de départ: 1 000,00 EUR
Prix spécial: 860,00 EUR

```

### Add non-breaking spaces to prices

[](#add-non-breaking-spaces-to-prices)

When formatting prices, spaces automatically get replaced by non-breaking space characters for use in text documents. This can be easily switched to an HTML context:

```
use Mistralys\CurrencyParser\PriceFilter;

$subject = setNonBreakingSpaceHTML()
    ->filterString($subject)
```

Output:

```
Prix de départ: 1 000,00 EUR
Prix spécial: 860,00 EUR

```

### Change the currency symbol

[](#change-the-currency-symbol)

By default, the currency filter makes no changes to the currency symbols used in the document. This means that a mixed symbol usage will remain the same even after formatting the numbers.

#### Change to currency symbols

[](#change-to-currency-symbols)

```
use Mistralys\CurrencyParser\PriceFilter;

$subject = setSymbolModeSymbol()
    ->filterString($subject);
```

Output:

```
With name: $1,000
With symbol: $1,000

```

#### Change to currency names

[](#change-to-currency-names)

```
use Mistralys\CurrencyParser\PriceFilter;

$subject = setSymbolModeSymbol()
    ->filterString($subject);
```

Output:

```
With name: $1,000
With symbol: $1,000

```

#### Change to country preferred style

[](#change-to-country-preferred-style)

For the Euro, the preferred style is to use the currency symbol for prices instead of the name.

```
use Mistralys\CurrencyParser\PriceFilter;

$subject = setSymbolModePreferred()
    ->filterString($subject);
```

Output:

```
With name: € 1 000
With symbol: € 1 000

```

Formatter usage
---------------

[](#formatter-usage)

### What is the formatter?

[](#what-is-the-formatter)

The formatter is used to format individual prices found in a text by the parser. It knows how to format prices according to the bundled currency locales, like American or Mexican Dollars, or French Euros. It can also be customised to format prices any way you like.

> NOTE: To format multiple prices at once, look at the Price Filter.

### Locale-based formatting

[](#locale-based-formatting)

Fire-and-forget formatting that uses the currency locale definitions.

```
use Mistralys\CurrencyParser\PriceFormatter;
use function Mistralys\CurrencyParser\parsePrice;

echo PriceFormatter::createLocale('USD')
    ->format(parsePrice('$ 1000'))
```

A locale formatter does not allow changing formatting details like the decimal separator. Only the symbol mode and space character can be adjusted:

```
use Mistralys\CurrencyParser\PriceFormatter;
use function Mistralys\CurrencyParser\parsePrice;

echo PriceFormatter::createLocale('USD')
    ->setNonBreakingSpaceHTML()
    ->setSymbolModeName()
    ->format(parsePrice('$ 1000'))
```

### Custom formatting

[](#custom-formatting)

Using a custom formatter, all formatting details can can be freely adjusted.

```
use Mistralys\CurrencyParser\PriceFormatter;
use function Mistralys\CurrencyParser\parsePrice;

$formatter = PriceFormatter::createCustom()
    ->setDecimalSeparator('[DECIMAL]')
    ->setThousandsSeparator('[THOUSAND]')
    ->setArithmeticSeparator('[ARITHMETIC]')
    ->setNonBreakingSpace('[SPACE]')
    ->setSymbolPosition(PriceFormatter::SYMBOL_POSITION_END)
    ->setSymbolSpaceAtTheEnd(PriceFormatter::SPACE_BEFORE);

echo $formatter->formatPrice(parsePrice('$ -1000.00'));
```

Output:

```
-[ARITHMETIC]1[THOUSAND]000[DECIMAL]00[SPACE]$

```

> NOTE: A formatter instance can be re-used as necessary.

### Custom formatter based on a locale

[](#custom-formatter-based-on-a-locale)

Let's say that we wish to use the default USD formatting, but instead of placing the symbol at the beginning (default behavior), we want to display it at the end.

We have to use a custom formatter for this, but we can use an existing locale formatter to fill out the default settings. All that's left to do then is overwrite the relevant settings.

```
use Mistralys\CurrencyParser\PriceFormatter;

$formatter = PriceFormatter::createCustom()
    ->configureWithLocale(\Mistralys\CurrencyParser\currencyLocale('USD'))
    ->setSymbolPositionAtTheEnd();
```

Filter usage
------------

[](#filter-usage)

### What is the price filter?

[](#what-is-the-price-filter)

The Filter is used to format multiple prices in text or markup documents, with a minimum of code, and leaving the rest of the document intact.

### Filtering a text document

[](#filtering-a-text-document)

The fire and forget version of filtering a document is to specify what kind of currencies to expect, and let the filter handle all the details based on how the currency is typically formatted.

```
use Mistralys\CurrencyParser\PriceFilter;

$formatted = PriceFilter::createForLocales('USD')
    ->filterString($subject);
```

### Filtering an HTML document

[](#filtering-an-html-document)

This works exactly like a text document, except that the non-breaking space character is adjusted to use the HTML style (which uses an HTML entity instead of the actual character).

```
use Mistralys\CurrencyParser\PriceFilter;

$formatted = PriceFilter::createForLocales('USD')
    ->setNonBreakingSpaceHTML()
    ->filterString($subject);
```

### Using custom formatters

[](#using-custom-formatters)

To use a custom formatter for a currency instead of the locale-based one, the formatter instance must be set separately.

```
use Mistralys\CurrencyParser\PriceFilter;
use Mistralys\CurrencyParser\PriceFormatter;

// Configure a custom formatter
$customFormatter = PriceFormatter::createCustom()
    ->setDecimalSeparator(' ')
    ->setThousandsSeparator(',')
    ->setSymbolPositionBeforeMinus()
    ->setSymbolModeName();

$formatted = PriceFilter::create()
    ->setFormatter('USD', $customFormatter)
    ->filterString($subject);
```

Custom formatters and locale formatters can be freely combined. In the example above, we used `PriceFilter::create()`, because all formatters were custom. Here, we use a default locale formatter for french prices, and a custom one for U.S. dollars:

```
use Mistralys\CurrencyParser\PriceFilter;
use Mistralys\CurrencyParser\PriceFormatter;

// Configure a custom formatter
$customFormatter = PriceFormatter::createCustom()
    ->setDecimalSeparator(' ')
    ->setThousandsSeparator(',')
    ->setSymbolPositionBeforeMinus()
    ->setSymbolModeName();

$formatted = PriceFilter::createForLocales('EUR_FR')
    ->setFormatter('USD', $customFormatter)
    ->filterString($subject);
```

Parser usage
------------

[](#parser-usage)

### What is the parser?

[](#what-is-the-parser)

The parser is able to find prices written in arbitrary texts, including within markup (HTML or XML). It can be used as a standalone utility to access price information, to do with as you please.

### Detecting specific currencies

[](#detecting-specific-currencies)

To be able to detect prices, the parser needs to know what kind of currencies to expect in the document. In the following example, we only use Euro prices.

```
use Mistralys\CurrencyParser\PriceParser;

$subject = 'Price of a basic subscription: 50,42 €.';

$prices = PriceParser::create()
    ->expectCurrency('EUR')
    ->findPrices($subject);
```

### Detecting all currencies

[](#detecting-all-currencies)

For performance reasons, it is best to limit the list currencies to search for in a document. If this cannot be determined reliably, you may use all of them:

```
use Mistralys\CurrencyParser\PriceParser;

$subject = '(document with prices here)';

$prices = PriceParser::create()
    ->expectAnyCurrency()
    ->findPrices($subject);
```

> Also see the next section on how to handle currencies that share the same currency symbol.

### Multiple possible currencies per symbol

[](#multiple-possible-currencies-per-symbol)

It is possible to add multiple currencies to the parser. However, it will not be able to tell them apart if they share the same symbol. Consider the following text:

```
use Mistralys\CurrencyParser\PriceParser;

$subject = expectCurrency('CAD')
    ->findPrices($subject);

echo $prices[0]->getCurrencyName(); // USD
echo $prices[1]->getCurrencyName(); // USD
```

The parser will not be able to tell which of those two prices are the CAD and USD ones. By default, the **parser will use `USD` in case of conflict with the `$` symbol**. Using currency names does not have this issue:

```
use Mistralys\CurrencyParser\PriceParser;

$subject = expectCurrency('CAD')
    ->findPrices($subject);

echo $prices[0]->getCurrencyName(); // CAD
echo $prices[1]->getCurrencyName(); // USD
```

### Setting default currencies per symbol

[](#setting-default-currencies-per-symbol)

The parser has built-in defaults for currency symbol conflicts, like `USD` for `$`. However, this can be adjusted if the target currency used in the document is known. Consider the following example:

```
use Mistralys\CurrencyParser\PriceParser;

$subject = setSymbolDefault('$', 'CAD')
    ->findPrices($subject);

echo $prices[0]->getCurrencyName(); // CAD
echo $prices[1]->getCurrencyName(); // CAD
echo $prices[3]->getCurrencyName(); // CAD
```

> If the document uses multiple currencies with the same symbol, this will not make it possible to distinguish between them. Only using currency names can solve such cases.

Mailcode compatibility
----------------------

[](#mailcode-compatibility)

The [Mailcode](https://github.com/Mistralys/mailcode) command preprocessor uses numbers as placeholders for commands when safeguarding them to apply formatting filters (more on the [reasoning behind this](https://github.com/Mistralys/mailcode#avoiding-delimiter-conflicts)). This can cause placeholders of variable commands to be falsely recognized as prices.

Example text with a variable command:

```
Price from a variable: {showvar: $FOO.PRICE} EUR

```

The `showvar` command is converted to a numeric placeholder by the safeguard feature:

```
Price from a variable: 9990000000001999 EUR

```

To avoid this being formatted into a price (and thus breaking the Mailcode command), simply enable the Mailcode support in the currency parser via the `expectMailcode()`method:

```
use Mailcode\Mailcode;
use Mistralys\CurrencyParser\PriceParser;
use Mistralys\CurrencyParser\PriceFilter;

$text = 'Price from a variable: {showvar: $FOO.PRICE} EUR';

// Replace Mailcode commands with placeholders
$safeguard = Mailcode::create()->createSafeguard($text);
$safeText = $safeguard->makeSafe();

$currencyParser = PriceParser::create()
    ->expectCurrency('EUR')
    ->expectMailcode();

// Format all currencies in the text
$formattedText = PriceFilter::create($currencyParser)
    ->filterString($safeText);

// Restore the Mailcode commands
$filteredText = $safeguard->makeWhole($formattedText);
```

> NOTE: This will only work with the default Mailcode placeholder delimiters. Using a custom delimiter is not supported.

Handling multi-currency documents
---------------------------------

[](#handling-multi-currency-documents)

In documents with multiple currencies, if they use the same symbol (USD and CAD for example), one must be set as default.

Philosophy
----------

[](#philosophy)

There is an excellent money library for PHP, [Money](https://github.com/moneyphp/money). This library does not attempt to reproduce the same functionality - it was developed for an application in particular, which requires the formatting to be fully whitespace-aware. The methodology in general is focused on the filtering aspect, whereas Money is a full-fledged financial calculation tool.

The two libraries can be used together: Prices have a method to get their value in money integer style.

```
// (int)5000
$money = \Mistralys\CurrencyParser\parsePrice('$50')->getAsMoney();
```

> NOTE: The built-int locale-based formatting may vary slightly from a library like Money. This is due to the formatting rules defined in the application for which the library was developed.

### Contributing

[](#contributing)

Contributions are always welcome. The library does not currently aim to include all worldwide currencies, but we are open tp any you may be able to add via pull requests. Look in the [Currencies](https://github.com/Mistralys/currency-parser/tree/main/src/Currencies)folder to get an overview of what's there.

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance45

Moderate activity, may be stable

Popularity26

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity58

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 98.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~65 days

Recently: every ~199 days

Total

14

Last Release

333d ago

PHP version history (2 changes)1.0.0PHP &gt;=7.4

1.1.1PHP ^7.4|^8.0

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/8895528?v=4)[Mistralys](/maintainers/Mistralys)[@Mistralys](https://github.com/Mistralys)

---

Top Contributors

[![Mistralys](https://avatars.githubusercontent.com/u/8895528?v=4)](https://github.com/Mistralys "Mistralys (153 commits)")[![daun](https://avatars.githubusercontent.com/u/22225348?v=4)](https://github.com/daun "daun (2 commits)")[![timxsarus](https://avatars.githubusercontent.com/u/15139309?v=4)](https://github.com/timxsarus "timxsarus (1 commits)")

---

Tags

currencyfilteringnormalizationparserprices

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/mistralys-currency-parser/health.svg)

```
[![Health](https://phpackages.com/badges/mistralys-currency-parser/health.svg)](https://phpackages.com/packages/mistralys-currency-parser)
```

###  Alternatives

[masterminds/html5

An HTML5 parser and serializer.

1.8k242.8M229](/packages/masterminds-html5)[sabberworm/php-css-parser

Parser for CSS Files written in PHP

1.8k191.2M65](/packages/sabberworm-php-css-parser)[jms/metadata

Class/method/property metadata management in PHP

1.8k152.8M88](/packages/jms-metadata)[jms/serializer-bundle

Allows you to easily serialize, and deserialize data of any complexity

1.8k89.3M627](/packages/jms-serializer-bundle)[hassankhan/config

Lightweight configuration file loader that supports PHP, INI, XML, JSON, and YAML files

97513.5M170](/packages/hassankhan-config)[meyfa/php-svg

Read, edit, write, and render SVG files with PHP

54613.9M42](/packages/meyfa-php-svg)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
