Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
60f071b
Usage info
dereuromark Nov 25, 2023
ed16470
Precision/Scale docs
dereuromark Nov 25, 2023
752ac99
History docs.
dereuromark Nov 26, 2023
1e9671c
Note about (monetary) alternatives
dereuromark Nov 28, 2023
f5f8664
Update README.md
dereuromark Nov 28, 2023
cb2c24f
Docs
dereuromark Nov 28, 2023
d8ba09c
Run composer normalize over composer.json
dereuromark Dec 4, 2023
45892c1
Test stringable classes for create (#12)
dereuromark Dec 7, 2023
c983ea0
Note about scale auto.
dereuromark Dec 7, 2023
0a5dd25
Update README.md
dereuromark Dec 7, 2023
5f2598d
Merge pull request #14 from php-collective/dereuromark-patch-1
dereuromark Dec 7, 2023
d6dbabb
Document meaning of scale
jhatlak Dec 20, 2023
0e8ee11
Merge pull request #15 from InvisibleSmiley/fix-scaledoc
dereuromark Dec 20, 2023
e6205ca
codecov-update
dereuromark Feb 8, 2024
3a12453
Merge pull request #16 from php-collective/dereuromark-patch-1
dereuromark Feb 9, 2024
1502edf
Check PHP84
dereuromark Oct 16, 2024
2f95de3
Merge pull request #17 from php-collective/php84
dereuromark Oct 16, 2024
539fd1d
Fix up PHPStan
dereuromark Mar 10, 2025
a9421cd
Fix up rounding for small values. (#18)
dereuromark Mar 10, 2025
fce3d88
Only require strict check as opt-in
dereuromark Apr 3, 2025
2b26490
Fix up precision loss for defined smaller scale.
dereuromark Apr 3, 2025
0c5f020
Add Renovate configuration
dereuromark Mar 8, 2026
f264333
Fix Renovate configuration
dereuromark Mar 8, 2026
49612bb
Allow PHPUnit 12 and 13 (#19)
dereuromark Sep 14, 2026
d8fc592
Fix parsing, negative zero, rounding and scientific notation edge cases
dereuromark Oct 11, 2026
a02decd
Require PHP 8.2 and update the dev tooling (#21)
dereuromark Oct 11, 2026
ede83d6
Keep four behavior changes out of 1.x
dereuromark Oct 11, 2026
763e5bc
Keep three more output changes out of 1.x
dereuromark Oct 11, 2026
6b787f5
Merge the 1.x fixes into next
dereuromark Oct 11, 2026
ce9ea39
Apply the behavior changes held back from 1.x
dereuromark Oct 11, 2026
5fd1e0a
Fix parsing, negative zero, rounding and scientific notation edge cas…
dereuromark Oct 11, 2026
a43e913
Add a documentation website (#22)
dereuromark Oct 11, 2026
81e9150
Add rounding modes, withScale(), allocation and helper methods
dereuromark Oct 11, 2026
a1ec406
Add rounding modes, withScale(), allocation and helper methods (#24)
dereuromark Oct 11, 2026
2548bba
Merge the 1.4 work into the 2.0 branch
dereuromark Oct 11, 2026
0bd7615
Merge master into the 2.0 branch
dereuromark Oct 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions .docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
ARG PHP_VERSION=8.2
ARG PHPUNIT_VERSION=10.4.0
ARG PHPSTAN_VERSION=1.10.38
ARG PHP_VERSION=8.5

FROM php:${PHP_VERSION}-cli-alpine
COPY --from=composer /usr/bin/composer /usr/bin/composer

ARG PHPUNIT_VERSION
ARG PHPSTAN_VERSION

RUN docker-php-ext-install bcmath && docker-php-ext-enable bcmath
RUN wget -O phpunit https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar && chmod +x phpunit
RUN wget -O phpstan https://github.com/phpstan/phpstan/releases/download/${PHPSTAN_VERSION}/phpstan.phar && chmod +x phpstan

4 changes: 1 addition & 3 deletions .env
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
PHP_VERSION=8.2
PHPUNIT_VERSION=10.4.0
PHPSTAN_VERSION=1.10.38
PHP_VERSION=8.5
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ Makefile export-ignore

# Remove directories for archives
.docker/ export-ignore
docs/ export-ignore
.github/ export-ignore
tests/ export-ignore
22 changes: 11 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ on:

jobs:
testsuite:
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php-version: ['8.1', '8.2', '8.3']
php-version: ['8.2', '8.3', '8.4', '8.5']

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6

- name: Setup PHP
uses: shivammathur/setup-php@v2
Expand All @@ -26,35 +26,35 @@ jobs:
coverage: pcov

- name: Composer install
continue-on-error: ${{ matrix.php-version == '8.3' }}
run: |
composer --version
composer install

- name: Run PHPUnit
continue-on-error: ${{ matrix.php-version == '8.3' }}
run: |
if [[ ${{ matrix.php-version }} == '8.1' ]]; then
if [[ ${{ matrix.php-version }} == '8.2' ]]; then
vendor/bin/phpunit --coverage-clover=coverage.xml
else
vendor/bin/phpunit
fi

- name: Code Coverage Report
if: success() && matrix.php-version == '8.1'
uses: codecov/codecov-action@v1
if: success() && matrix.php-version == '8.2'
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}

validation:
name: Coding Standard & Static Analysis
runs-on: ubuntu-22.04
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
php-version: '8.2'
extensions: mbstring, intl, bcmath
coverage: none

Expand Down
60 changes: 60 additions & 0 deletions .github/workflows/deploy-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Deploy Documentation

on:
push:
branches:
- master
paths:
- 'docs/**'
- '.github/workflows/deploy-docs.yml'
workflow_dispatch:

permissions:
contents: read

concurrency:
group: pages
cancel-in-progress: false

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 24
cache: npm
cache-dependency-path: docs/package-lock.json

- name: Install dependencies
run: npm ci
working-directory: docs

- name: Build with VitePress
run: npm run docs:build
working-directory: docs

- name: Upload artifact
uses: actions/upload-pages-artifact@v5
with:
path: docs/.vitepress/dist

deploy:
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
needs: build
runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v5
69 changes: 45 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,73 @@
[![CI](https://github.com/php-collective/decimal-object/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/php-collective/decimal-object/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/php-collective/decimal-object/branch/master/graph/badge.svg?token=L1thFB9nOG)](https://codecov.io/gh/php-collective/decimal-object)
[![Latest Stable Version](https://poser.pugx.org/php-collective/decimal-object/v/stable.svg)](https://packagist.org/packages/php-collective/decimal-object)
[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%208.1-8892BF.svg)](https://php.net/)
[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%208.2-8892BF.svg)](https://php.net/)
[![PHPStan](https://img.shields.io/badge/PHPStan-level%208-brightgreen.svg?style=flat)](https://phpstan.org/)
[![License](https://poser.pugx.org/php-collective/decimal-object/license)](https://packagist.org/packages/php-collective/decimal-object)

Decimal value object for PHP.

## Documentation

**<https://php-collective.github.io/decimal-object/>**

## Background
When working with monetary values, normal data types like int or float are not suitable for exact arithmetic.
Try out the following in PHP:

Floats cannot represent most decimal fractions exactly, which makes them unsuitable for money and other values that must add up:

```php
var_dump(0.1 + 0.2); // float(0.3)
var_dump(0.1 + 0.2 - 0.3); // float(5.5511151231258E-17)
var_dump(0.1 + 0.2 === 0.3); // bool(false)
```

Handling them as string is a workaround, but as value object you can more easily encapsulate some of the logic.
Handling such values as strings works, and a value object keeps the logic for it in one place:

### Alternatives
Solutions like https://php-decimal.io require a PHP extension (would make it faster, but also more difficult for some
servers to be available). For details see the [wiki](https://github.com/php-collective/decimal-object/wiki).
```php
use PhpCollective\DecimalObject\Decimal;

$total = Decimal::create('0.1')->add('0.2');

Note: If you are looking for pre 8.1 versions, check out legacy library (https://github.com/spryker/decimal-object).
echo $total; // 0.3
var_dump($total->equals('0.3')); // bool(true)
```

## Features

- Super strict on precision/scale. Does not lose significant digits on its own. You need to `trim()` for this manually.
- Speaking API (no le, gt methods).
- Basic math operations and checks supported.
- Immutability.
- Handle very large and very small numbers.
- Strict about precision and scale. Significant digits are only dropped when you `trim()` or round.
- Readable API: `add()`, `greaterThan()`, `isZero()`.
- Arithmetic, rounding, comparison and conversion.
- Immutable.
- Handles numbers beyond the integer and float range.
- No custom PHP extension, only `bcmath`.

## Installation

### Requirements

- `bcmath` PHP extension enabled

### Composer (preferred)
```
composer require php-collective/decimal-object
```

Requires PHP 8.2+ and the `bcmath` extension. PHP 8.1 is covered by the 1.3 releases. For anything older, use the [legacy library](https://github.com/spryker/decimal-object).

## Usage

See [Documentation](/docs) for more details.
- [Getting started](https://php-collective.github.io/decimal-object/guide/getting-started)
- [Arithmetic](https://php-collective.github.io/decimal-object/guide/arithmetic)
- [Precision and scale](https://php-collective.github.io/decimal-object/guide/scale)
- [Rounding](https://php-collective.github.io/decimal-object/guide/rounding)
- [API reference](https://php-collective.github.io/decimal-object/reference/api)

## Integrations

- [dereuromark/cakephp-decimal](https://dereuromark.github.io/cakephp-decimal/) as decimal type for the CakePHP ORM.

See [Alternatives](https://php-collective.github.io/decimal-object/reference/alternatives) for how this library compares to php-decimal, brick/math and the money libraries.

## Contributing

Pull requests are welcome:

- Target `master` for bug fixes and backwards compatible improvements.
- Target `next` (the next major version) for anything that breaks backwards compatibility.

### Implementations
The following libraries are using the `Decimal` value object:
## History

- [dereuromark/cakephp-decimal](https://github.com/dereuromark/cakephp-decimal) as decimal type replacement for CakePHP ORM.
The library was written in 2019 for the [Spryker](https://spryker.com/) commerce framework and has been used there in order and price calculations since. This repository is the independently maintained continuation for the PHP ecosystem as a whole.
4 changes: 1 addition & 3 deletions compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ services:
context: .
dockerfile: .docker/Dockerfile
args:
PHP_VERSION: "${PHP_VERSION:-8.2}"
PHPUNIT_VERSION: "${PHPUNIT_VERSION:-10.4.0}"
PHPSTAN_VERSION: "${PHPSTAN_VERSION:-1.10.38}"
PHP_VERSION: "${PHP_VERSION:-8.5}"
volumes:
- ./:/code
working_dir: /code
46 changes: 29 additions & 17 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
{
"name": "php-collective/decimal-object",
"description": "PHP decimal handling as value object",
"type": "library",
"license": "MIT",
"type": "library",
"keywords": [
"decimal",
"value-object",
"bcmath",
"precision",
"arbitrary-precision",
"math"
],
"authors": [
{
"name": "The PHP Collective",
Expand All @@ -13,16 +21,22 @@
"homepage": "https://spryker.com"
}
],
"support": {
"issues": "https://github.com/php-collective/decimal-object/issues",
"source": "https://github.com/php-collective/decimal-object"
},
"require": {
"php": ">=8.1",
"php": ">=8.2",
"ext-bcmath": "*",
"ext-json": "*"
},
"require-dev": {
"phpunit/phpunit": "^10.3.0",
"php-collective/code-sniffer": "^0.2.1",
"phpstan/phpstan": "^1.0.0"
"php-collective/code-sniffer": "^0.6.8",
"phpstan/phpstan": "^2.0.0",
"phpunit/phpunit": "^11.5.0 || ^12.0.0 || ^13.0.0"
},
"minimum-stability": "stable",
"prefer-stable": true,
"autoload": {
"psr-4": {
"PhpCollective\\DecimalObject\\": "src/"
Expand All @@ -33,25 +47,23 @@
"PhpCollective\\DecimalObject\\Test\\": "tests/"
}
},
"minimum-stability": "stable",
"prefer-stable": true,
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
},
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"scripts": {
"test": "phpunit",
"test-coverage": "phpunit --log-junit tmp/coverage/unitreport.xml --coverage-html tmp/coverage --coverage-clover tmp/coverage/coverage.xml",
"stan": "phpstan analyse",
"cs-check": "vendor/bin/phpcs",
"cs-fix": "vendor/bin/phpcbf",
"lowest": "validate-prefer-lowest",
"lowest-setup": "composer update --prefer-lowest --prefer-stable --prefer-dist --no-interaction && cp composer.json composer.backup && composer require --dev dereuromark/composer-prefer-lowest && mv composer.backup composer.json",
"cs-check": "vendor/bin/phpcs",
"cs-fix": "vendor/bin/phpcbf"
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
"stan": "phpstan analyse",
"test": "phpunit",
"test-coverage": "phpunit --log-junit tmp/coverage/unitreport.xml --coverage-html tmp/coverage --coverage-clover tmp/coverage/coverage.xml"
}
}
3 changes: 3 additions & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
.vitepress/dist/
.vitepress/cache/
53 changes: 53 additions & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { defineConfig } from 'vitepress'

export default defineConfig({
title: 'Decimal Object',
description: 'Immutable decimal value object for PHP, built on bcmath.',
base: '/decimal-object/',
srcExclude: ['README.md'],
head: [['link', { rel: 'icon', type: 'image/svg+xml', href: '/decimal-object/favicon.svg' }]],
themeConfig: {
logo: '/logo.svg',
nav: [
{ text: 'Installation', link: '/guide/installation' },
{ text: 'Getting started', link: '/guide/getting-started' },
{ text: 'API', link: '/reference/api' },
{
text: 'Ecosystem',
items: [
{ text: 'Integrations', link: '/reference/integrations' },
{ text: 'CakePHP Decimal', link: 'https://dereuromark.github.io/cakephp-decimal/' },
{ text: 'Packagist', link: 'https://packagist.org/packages/php-collective/decimal-object' },
],
},
],
sidebar: [
{
text: 'Guide',
items: [
{ text: 'Installation', link: '/guide/installation' },
{ text: 'Getting started', link: '/guide/getting-started' },
{ text: 'Creating decimals', link: '/guide/creating' },
{ text: 'Arithmetic', link: '/guide/arithmetic' },
{ text: 'Precision and scale', link: '/guide/scale' },
{ text: 'Rounding', link: '/guide/rounding' },
{ text: 'Comparison and checks', link: '/guide/comparison' },
{ text: 'Conversion', link: '/guide/conversion' },
],
},
{
text: 'Reference',
items: [
{ text: 'API', link: '/reference/api' },
{ text: 'Integrations', link: '/reference/integrations' },
{ text: 'Alternatives', link: '/reference/alternatives' },
{ text: 'Upgrading', link: '/reference/upgrading' },
],
},
],
search: { provider: 'local' },
socialLinks: [{ icon: 'github', link: 'https://github.com/php-collective/decimal-object' }],
editLink: { pattern: 'https://github.com/php-collective/decimal-object/edit/master/docs/:path' },
footer: { message: 'Released under the MIT License.', copyright: 'Copyright The PHP Collective' },
},
})
Loading
Loading