Skip to content

Add a NumberType that maps to the BcMath\Number value object#6686

Merged
derrabus merged 1 commit into
doctrine:4.3.xfrom
derrabus:feature/number-type
Jan 6, 2025
Merged

Add a NumberType that maps to the BcMath\Number value object#6686
derrabus merged 1 commit into
doctrine:4.3.xfrom
derrabus:feature/number-type

Conversation

@derrabus

@derrabus derrabus commented Jan 5, 2025

Copy link
Copy Markdown
Member
Q A
Type feature
Fixed issues #6644

Summary

PHP 8.4 introduces a new Number class (RFC, php/php-src#13741) that feels like a perfect fit for DECIMAL values. This PR introduces a new NumberType class and a corresponding Types::NUMBER constant which maps decimal values to Number objects instead of plain strings.

greg0ire
greg0ire previously approved these changes Jan 5, 2025
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v3"
with:
composer-options: "--ignore-platform-req=php+"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is necessary because of Psalm, right?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I know, we need to kick it.

@morozov morozov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to add some test coverage for value conversion? There is a functional BigIntTypeTest, so maybe add one for the new type as well.

Comment thread tests/Functional/TypeConversionTest.php Outdated
$originalValue = new Number('13.37');
$dbValue = $this->processValue(Types::NUMBER, $originalValue);

self::assertSame(0, $originalValue->compare($dbValue));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It took me a minute to understand why zero is expected. I'm curious if assertEquals() can be used instead.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot use assertEquals() because PHPUnit 10 would compare two Number objects by comparing all properties. That's a problem because new Number('13.37') and new Number('13.3700') should be considered equal despite all properties being different. And that's a problem for us because the database might decide to normalize decimals by stripping or padding trailing zeros.

That's an issue that could be fixed upstream however. I can look into this, but given PHPUnit's release schedule, that fix would land in PHPUnit 12 earliest.

For now, the compare() method or the overloaded operators == and <=> are the proper ways of checking if two numbers are equal. Our PHPCS rules would however fix assertTrue($a == $b) to assertEquals(), so I decided to not use that either. But I've alternated between compare() and <=>, so I've now changed all tests to consistently use the spaceship operator. The value range of that operator is defined as [-1, 0, 1], so maybe that makes things a little clearer.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've opened sebastianbergmann/comparator#121 to address this issue.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think <=> makes it clearer since it's more visually distinct. Thanks for the explanation and addressing it upstream. I believe, ultimately, using assertEquals() will be the clearest approach as it's the standard.

@derrabus
derrabus force-pushed the feature/number-type branch from cf6a9fe to 8f39a40 Compare January 6, 2025 07:11
@derrabus derrabus changed the title Add a NumberType that maps to the BCMath\Number value object Add a NumberType that maps to the BcMath\Number value object Jan 6, 2025
@derrabus

derrabus commented Jan 6, 2025

Copy link
Copy Markdown
Member Author

Would it be possible to add some test coverage for value conversion? There is a functional BigIntTypeTest, so maybe add one for the new type as well.

The PR already contains two new NumberTest classes (unit + functional). Did I miss important test cases?

@eugene-borovov

Copy link
Copy Markdown

There is a polyfill for BcMath\Number. Is it worth to use it?

@derrabus

derrabus commented Jan 6, 2025

Copy link
Copy Markdown
Member Author

There is a polyfill for BcMath\Number.

I would expect that my new type is compatible with that polyfill.

Is it worth to use it?

That's something you have to decide for yourself. 🙂

@morozov

morozov commented Jan 6, 2025

Copy link
Copy Markdown
Member

Did I miss important test cases?

The previous inline coverage report shown quite a few places in the conversion code as uncovered, but probably it was a glitch. Now, the diff coverage is at 100%, so we're good.

@derrabus
derrabus merged commit eea8aaf into doctrine:4.3.x Jan 6, 2025
@derrabus
derrabus deleted the feature/number-type branch January 6, 2025 18:00
derrabus added a commit to derrabus/dbal that referenced this pull request Jan 6, 2025
* 4.3.x:
  Enable platformOptions to be considered for ColumnDiff (PostgreSQL jsonb support) (doctrine#6693)
  Ignore new PHPStan errors
  Cleanup obsolete PHPStan ignore rules (doctrine#6697)
  Add a `NumberType` that maps to the `BcMath\Number` value object (doctrine#6686)
  PHPStan 2.1.1 (doctrine#6690)
  PHPUnit 10.5.39 (doctrine#6692)
  PHPUnit 9.6.22 (doctrine#6691)
  Bump doctrine/.github from 6.0.0 to 7.1.0 (doctrine#6649)
  Bump doctrine/.github from 5.3.0 to 6.0.0 (doctrine#6642)
derrabus added a commit to derrabus/dbal that referenced this pull request Jan 6, 2025
* 4.3.x:
  Enable platformOptions to be considered for ColumnDiff (PostgreSQL jsonb support) (doctrine#6693)
  Ignore new PHPStan errors
  Cleanup obsolete PHPStan ignore rules (doctrine#6697)
  Add a `NumberType` that maps to the `BcMath\Number` value object (doctrine#6686)
  PHPStan 2.1.1 (doctrine#6690)
  PHPUnit 10.5.39 (doctrine#6692)
  PHPUnit 9.6.22 (doctrine#6691)
  Bump doctrine/.github from 6.0.0 to 7.1.0 (doctrine#6649)
  Bump doctrine/.github from 5.3.0 to 6.0.0 (doctrine#6642)
@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Jan 7, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use the BcMath\Number as new Type to work easier with arbitrary precision numbers

4 participants