Download the PHP package brick/money without Composer

On this page you can find all versions of the php package brick/money. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package money

Brick\Money

A money and currency library for PHP.

Build Status Coverage Latest Stable Version Total Downloads License

Introduction

This library provides immutable classes to work with monies and currencies, with exact arithmetic and explicit control over rounding — avoiding the silent rounding errors inherent to floating-point.

It is based on brick/math and handles exact calculations on monies of any size.

Installation

This library is installable via Composer:

Requirements

This library requires PHP 8.2 or later.

For PHP 8.1 compatibility, you can use version 0.10. For PHP 8.0, you can use version 0.8. For PHP 7.4, you can use version 0.7. For PHP 7.1, 7.2 & 7.3, you can use version 0.5. Note that these PHP versions are EOL and not supported anymore. If you're still using one of these PHP versions, you should consider upgrading as soon as possible.

Although not required, it is recommended that you install the GMP or BCMath extension to speed up calculations.

Project status & release process

While this library is still under development, it is well tested and should be stable enough to use in production environments.

The current releases are numbered 0.x.y. When a non-breaking change is introduced (adding new methods, optimizing existing code, etc.), y is incremented.

When a breaking change is introduced, a new 0.x version cycle is always started.

It is therefore safe to lock your project to a given release cycle, such as 0.13.*.

If you need to upgrade to a newer release cycle, check the release history for a list of changes introduced by each further 0.x.0 version.

Currency updates

This library is based on the latest ISO 4217 standard. This is a living standard, so updates to currencies are expected to happen regularly.

Updates to the following features will be considered breaking changes, and will only be released in a new major version after 1.0:

The following features are evolving constantly, they will not be considered breaking changes and may be updated in minor releases after 1.0:

Creating a Money

From a regular currency value

To create a Money, call the of() factory method:

If the given amount does not fit in the currency's default number of decimal places (2 for USD), you can pass a RoundingMode:

Note that the rounding mode is only used once, for the value provided in of(); it is not stored in the Money object, and any subsequent operation will still need to be passed a RoundingMode when necessary.

From minor units (cents)

Alternatively, you can create a Money from a number of "minor units" (cents), using the ofMinor() method:

Basic operations

Money is an immutable class: its value never changes, so it can be safely passed around. All operations on a Money therefore return a new instance:

You can add and subtract Money instances as well:

If the two Money instances are not of the same currency, an exception is thrown:

If the result needs rounding, a rounding mode must be passed as second parameter, or an exception is thrown:

Comparing monies

You can compare two Money instances using the following methods:

These methods accept either a number or a Money instance. If the argument is a Money instance, it must be of the same currency as the Money instance on which the method is called, or an exception is thrown.

If you need to compare amount & currency without throwing on currency mismatch, you can use isSameValueAs() instead of isEqualTo():

Comparison methods on Money instances only compare monies of the same currency. To compare monies in different currencies using exchange rates, see Comparing monies across currencies.

Checking the sign

You can inspect the sign of a Money instance using the following methods:

Money contexts

By default, monies have the official scale for the currency, as defined by the ISO 4217 standard (for example, EUR and USD have 2 decimal places, while JPY has 0) and increment by steps of 1 minor unit (cent); they internally use what is called the DefaultContext. You can change this behaviour by providing a Context instance. All operations on Money return another Money with the same context. Each context targets a particular use case:

Cash rounding

Some currencies do not allow the same increments for cash and cashless payments. For example, CHF (Swiss Franc) has 2 fraction digits and allows increments of 0.01 CHF, but Switzerland does not have coins of less than 5 cents, or 0.05 CHF.

You can deal with such monies using CashContext:

Custom scale

You can use custom scale monies by providing a CustomContext:

Auto scale

If you need monies that adjust their scale to fit the operation result, then AutoContext is for you:

Note that it is not advised to use AutoContext to represent an intermediate calculation result: in particular, it cannot represent the result of all divisions, as some of them may lead to an infinite repeating decimal, which would throw an exception. For these use cases, RationalMoney is what you need. Head on to the next section!

Advanced calculations

You may occasionally need to chain several operations on a Money, and only apply a rounding mode on the very last step; if you applied a rounding mode on every single operation, you might end up with a different result. This is where RationalMoney comes into play. This class internally stores the amount as a rational number (a fraction). You can create a RationalMoney from a Money, and conversely:

The intermediate results are represented as fractions, and no rounding is ever performed. The final toContext() method converts it to a Money, applying a context and a rounding mode. Most of the time you want the result in the same context as the original Money, which is what the example above does. But you can really apply any context:

Money allocation

Splitting

You can easily split a Money into a number of parts:

With SplitMode::ToFirst, the remainder is distributed one step at a time to the first parts. You can also use SplitMode::Separate to get the remainder as a separate last element:

Allocating

You can also allocate a Money according to a list of ratios. Say you want to distribute a profit of 987.65 CHF to 3 shareholders, having shares of 48%, 41% and 11% of a company:

It plays well with cash roundings, too:

[!TIP] Ratios can be any type of number (integer, decimal, rational) and do not need to add up to 100.

Several allocation modes are available. For example, given 1.00 USD allocated by [2, 3, 1]:

Mode Result
FloorToFirst
Proportional floor amounts, remainder distributed to first allocatees (Martin Fowler method)
0.34, 0.50, 0.16
FloorToLargestRemainder
Proportional floor amounts, remainder distributed to largest fractional remainders (Hamilton method)
0.33, 0.50, 0.17
FloorToLargestRatio
Proportional floor amounts, remainder distributed to largest ratios
0.33, 0.51, 0.16
FloorSeparate
Proportional floor amounts, remainder returned as a separate last element
0.33, 0.50, 0.16, 0.01
BlockSeparate
Only complete blocks allocated, remainder returned as a separate last element
0.32, 0.48, 0.16, 0.04

Money bags (mixed currencies)

You may sometimes need to add monies in different currencies together. MoneyBag comes in handy for this:

You can add any kind of money to a MoneyBag: a Money, a RationalMoney, or even another MoneyBag.

What can you do with a MoneyBag? Well, you can convert it to a Money in the currency of your choice, using a CurrencyConverter. Keep reading!

Currency conversion

This library ships with a CurrencyConverter that can convert any kind of money (Money, RationalMoney or MoneyBag) to a Money in another currency:

The converter performs the most precise calculation possible, internally representing the result as a rational number until the very last step.

To use the currency converter, you need an ExchangeRateProvider. Several implementations are provided, among which:

ConfigurableProvider

This provider allows you to configure exchange rates manually using a builder:

BaseCurrencyProvider

This provider builds on top of another exchange rate provider, for the quite common case where all your available exchange rates are relative to a single currency. For example, the exchange rates provided by the European Central Bank are all relative to EUR. You can use them directly to convert EUR to USD, but not USD to EUR, let alone USD to GBP.

This provider will combine exchange rates to get the expected result:

[!TIP] Notice that exchange rate providers can return rational numbers (fractions)!

PdoProvider

This provider reads exchange rates from a database table:

PdoProvider supports fixed source or target currency, numeric currency codes, dimensions, and static WHERE conditions. Check the PdoProviderBuilder class for more information.

Dimensions

Dimensions allow you to narrow exchange rate lookups beyond just a currency pair. For example, if your exchange rates table includes a date or rate type, you can bind these as dimensions:

Each dimension binding is a callback that receives the dimension value and returns a SqlCondition (an SQL fragment with positional parameters), or null to skip filtering on that dimension.

You can then pass dimensions when looking up an exchange rate:

Dimensions also flow through the CurrencyConverter:

A dimension binding can also accept complex types. For example, you can accept a DateTimeInterface and derive multiple SQL conditions from it:

If your table may contain multiple matching rows (e.g. daily rates within a month), use orderBy() to select the first match:

[!NOTE] If a dimension is passed that has no binding, the provider returns null (rate not found). Conversely, if a bound dimension is not passed, its condition is simply omitted from the query — this may cause multiple rows to match and throw an exception unless orderBy() is configured.

CachedProvider

This provider wraps another provider and caches the results using a PSR-16 cache. Both found and not-found rates are cached:

By default, an in-memory array cache is used. You can pass your own PSR-16 cache implementation and a TTL:

Dimensions are included in the cache key. Scalars, null, DateTimeInterface, and Stringable values are supported out of the box. For other object types, pass a custom normalizer:

If a dimension value is not cacheable (unsupported object type and no custom normalizer), the cache is bypassed and the wrapped provider is queried directly.

ChainProvider

This provider tries multiple providers in order and returns the first non-null result:

This is useful for combining providers — for example, different providers each supporting specific currency pairs or dimensions. Dimensions are passed through to each provider unchanged.

Write your own provider

Writing your own provider is easy: the ExchangeRateProvider interface has just one method, getExchangeRate(), that takes the currency codes, optional dimensions, and returns a number or null if the rate is not found:

Comparing monies across currencies

In addition to performing currency conversions, you can also use an ExchangeRateProvider to compare monies in different currencies, using a MoneyComparator:

Each method accepts two Monetary operands — a Money, RationalMoney, or MoneyBag:

The comparator also has min() and max() methods, which accept any number of monies and return the smallest/largest as the original instance, unchanged.

Comparison modes

The second argument of the MoneyComparator constructor selects how two monies are compared:

Mode Supported money instances Description
PairwiseMode Money, RationalMoney Converts the first operand into the second operand's currency (without rounding), then compares. Most precise for a single pair, but with asymmetric rates it can be non-transitive (A < B, B < C and C < A all at once), so min()/max() results may depend on argument order.
BaseCurrencyMode Money, RationalMoney, MoneyBag Converts both operands to a common base currency, then compares. Ordering is always consistent (if A ≤ B and B ≤ C then A ≤ C), so min()/max() results never depend on argument order.

BaseCurrencyMode takes the base currency as its constructor argument:

Dimensions

If your ExchangeRateProvider supports dimensions, you can provide them as the third constructor parameter:

Custom currencies

Money supports ISO 4217 currencies by default. You can also use custom currencies by creating a Currency instance. Let's create a Bitcoin currency:

You can now use this Currency instead of a currency code:

[!WARNING] Do not create multiple Currency instances with the same currency code but different data. The library identifies currencies by code, so conflicting instances used together may lead to undefined behaviour.

Formatting

Formatting requires the intl extension.

Money objects can be formatted according to a given locale:

Alternatively, you can format Money objects with your own instance of NumberFormatter, which gives you room for customization:

[!IMPORTANT] Because formatting is performed using NumberFormatter, the amount is converted to floating point in the process; so discrepancies can appear when formatting very large monetary values.

Storing Money objects in a database

Persisting the amount

Persisting the currency

[!NOTE] Numeric currency codes of ISO currencies may be reassigned over time, so prefer alphabetical currency codes whenever possible.

Using an ORM

If you're using an ORM such as Doctrine, it is advised to store the amount and currency separately, and perform conversion in the getters/setters:

FAQ

How does this project compare with moneyphp/money?

Please see this discussion.

PHPStan extension

A third-party PHPStan extension is available for this library. It provides more specific throw type narrowing for brick/money methods, so that PHPStan can infer the exact exception classes thrown. Note that this extension is not maintained by the author of brick/money.


All versions of money with dependencies

PHP Build Version
Package Version
Requires php Version ^8.2
brick/math Version ~0.15.0 || ~0.16.0 || ~0.17.0 || ~0.18.0
psr/simple-cache Version ^2.0 || ^3.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package brick/money contains the following files

Loading the files please wait ...