Responsive images
Added dimensions to footer icons
Bumped spatie/schema-org to access shipping details on Product
Bumped required PHP version to 7.4
Fixed Product structured data, Google export and meta tags
Removed unused psalm-suppress
Fixed Money::ratioOf test
Yes, it makes sense for ratioOf
to throw an exception on unmatched currencies, especially that mod
already does that. I made a PR.
I also added a test case for Money::mod
which already performs currency check.
fixes #732
Document compare() method
Merge pull request #621 from half0wl/docs/document-compare-fn
Documentation: Add docs for compare() method
Improve tests of parsers (#586)
Improve tests of parsers
Fix the codestyle
Remove unused uses
Revert changes regarding prophesize
update actions
This patch attempts to make quick money out of moneyphp/money
In this change, we bumped relevant dependencies to stick to php:^7.3
as minimum
supported php
version (since 7.2
is EOL'd and no longer covered by security fixes).
To do that, we upgraded all dependencies, upgraded spec files to comply with newest phpspec.
This currently means that we have a few broken scenarios and failures:
---- failed examples
Money/Parser/DecimalMoneyParser
47 ✘ throws an exception when money includes currency symbol
expected exception of class "Money\Exception\ParserExc...", but got
[exc:PhpSpec\Exception\Example\ErrorException("16384: Passing a currency as string is deprecated since 3.1 and
will be removed in 4.0. Please pass a Money\Currency instance instead. in
/home/ocramius/Documents/moneyphp/money/src/Parser/DecimalMoneyParser.php line 50")].
Money/Parser/DecimalMoneyParser
52 ✘ throws an exception when money is not a valid decimal
expected exception of class "Money\Exception\ParserExc...", but got
[exc:PhpSpec\Exception\Example\ErrorException("16384: Passing a currency as string is deprecated since 3.1 and
will be removed in 4.0. Please pass a Money\Currency instance instead. in
/home/ocramius/Documents/moneyphp/money/src/Parser/DecimalMoneyParser.php line 50")].
---- broken examples
Money/Exchange/ExchangerExchange
27 ! is initializable
could not reflect class Exchanger\Exchanger as it is marked final.
Money/Exchange/ExchangerExchange
32 ! is an exchange
could not reflect class Exchanger\Exchanger as it is marked final.
Money/Exchange/ExchangerExchange
37 ! exchanges currencies
could not reflect class Exchanger\Exchanger as it is marked final.
Money/Exchange/ExchangerExchange
53 ! throws an exception when cannot exchange currencies
could not reflect class Exchanger\Exchanger as it is marked final.
Money/Parser/DecimalMoneyParser
31 ! parses money
16384: Passing a currency as string is deprecated since 3.1 and will be removed in 4.0. Please pass a Money\Currency
instance instead. in /home/ocramius/Documents/moneyphp/money/src/Parser/DecimalMoneyParser.php line 50
29 specs
185 examples (178 passed, 2 failed, 5 broken)
146ms
Adapted PHPUnit tests to comply with the new PHPUnit 9.5+ signatures
Removed symfony/phpunit-bridge
, which is just noise (always has been)
Removed deprecation handler environment variables, now unused
Compatibility with PHPUnit 9.5+ - if we expect deprecations to be raised, then they should be raised
No suppressing them, since otherwise they effectively go unnoticed. Having a suppressed trigger_error()
means
that only side-effects get run, instead of proper exception conversion.
Added simplistic benchmarks about money instantiation, comparison and number operations
These benchmarks cover the "most used" functionality of Money
, and should highlight any
computational complexity overhead.
Added benchmarks for Money::sum()
, Money::min()
, Money::max()
and Money::avg()
Added benchmarks for Number::fromString()
, which is used a lot in number internals
Run benchmarks as part of composer test
, to avoid them bit-rotting and becoming unusable later on
Imported global functions to allow OpCache to optimize away well-known internal functions
Overall really hard to tell if the results are legit, but there are some improvements:
❯ php -dopcache.enable_cli=1 ./vendor/bin/phpbench run --ref=original --retry-threshold=5 --iterations=10
PHPBench @git_tag@ running benchmarks...
with configuration file: /home/ocramius/Documents/moneyphp/money/phpbench.json
with PHP version 8.0.3, xdebug ❌, opcache ✔
\Benchmark\Money\NumberInstantiationBench
benchConstructorWithZeroIntegerAmount...R1 I0 - [Mo575.630μs vs Mo591.581μs] -2.70% (±2.20%)
benchConstructorWithPositiveIntegerAmou.R7 I9 - [Mo551.930μs vs Mo550.683μs] +0.23% (±3.02%)
benchConstructorWithNegativeIntegerAmou.R1 I1 - [Mo554.108μs vs Mo580.812μs] -4.60% (±1.80%)
benchConstructorWithZeroAndFractionalAm.R1 I3 - [Mo543.759μs vs Mo595.014μs] -8.61% (±1.77%)
benchConstructorWithFractionalAmount....R1 I1 - [Mo589.360μs vs Mo611.898μs] -3.68% (±1.92%)
benchConstructorWithNegativeFractionalA.R1 I0 - [Mo573.149μs vs Mo580.123μs] -1.20% (±2.22%)
\Benchmark\Money\MoneyOperationBench
benchAdd................................R1 I6 - [Mo999.123μs vs Mo987.689μs] +1.16% (±2.42%)
benchSubtract...........................R1 I9 - [Mo985.683μs vs Mo936.192μs] +5.29% (±1.70%)
benchMultiply...........................R1 I7 - [Mo1.003ms vs Mo1.057ms] -5.11% (±2.00%)
benchDivide.............................R1 I9 - [Mo946.427μs vs Mo1.031ms] -8.19% (±3.11%)
benchRatioOf............................R1 I2 - [Mo985.380μs vs Mo989.503μs] -0.42% (±2.17%)
benchMod................................R2 I5 - [Mo391.671μs vs Mo401.023μs] -2.33% (±2.37%)
benchIsSameCurrency.....................R1 I4 - [Mo2.000μs vs Mo2.000μs] 0.00% (±0.00%)
benchIsZero.............................R10 I9 - [Mo384.644μs vs Mo426.642μs] -9.84% (±1.56%)
benchAbsolute...........................R2 I9 - [Mo423.309μs vs Mo396.644μs] +6.72% (±2.35%)
benchNegative...........................R6 I9 - [Mo981.397μs vs Mo983.110μs] -0.17% (±2.55%)
benchIsPositive.........................R3 I9 - [Mo386.301μs vs Mo392.182μs] -1.50% (±2.37%)
benchCompare............................R7 I8 - [Mo387.603μs vs Mo397.301μs] -2.44% (±3.22%)
benchLessThan...........................R3 I9 - [Mo407.575μs vs Mo390.164μs] +4.46% (±2.31%)
benchLessThanOrEqual....................R1 I9 - [Mo425.425μs vs Mo430.164μs] -1.10% (±1.34%)
benchEquals.............................R1 I7 - [Mo2.000μs vs Mo3.000μs] -33.33% (±0.00%)
benchGreaterThan........................R1 I7 - [Mo390.366μs vs Mo390.450μs] -0.02% (±2.10%)
benchGreaterThanOrEqual.................R2 I9 - [Mo412.262μs vs Mo411.738μs] +0.13% (±1.99%)
\Benchmark\Money\MoneyInstantiationBench
benchConstructorWithZeroIntegerAmount...R2 I4 - [Mo904.501μs vs Mo898.483μs] +0.67% (±2.20%)
benchConstructorWithPositiveIntegerAmou.R1 I8 - [Mo915.419μs vs Mo937.671μs] -2.37% (±2.11%)
benchConstructorWithNegativeIntegerAmou.R1 I5 - [Mo896.722μs vs Mo909.286μs] -1.38% (±1.30%)
benchConstructorWithZeroStringAmount....R2 I4 - [Mo908.315μs vs Mo933.039μs] -2.65% (±2.32%)
benchConstructorWithPositiveStringAmoun.R1 I8 - [Mo890.975μs vs Mo857.589μs] +3.89% (±1.99%)
benchConstructorWithNegativeStringAmoun.R1 I2 - [Mo858.750μs vs Mo904.536μs] -5.06% (±2.54%)
Subjects: 29, Assertions: 0, Failures: 0, Errors: 0
Enforcing Currency#__construct()
to require a string
as argument, removing useless test related to that
Inlined fetching of Calculator
inside Money
to avoid calling getCalculator()
all the time
This is a minimal improvement on a very hot execution path
Removed the need to create a Number
instance in BcMathCalculator#multiply()
and #divide()
Also here, no noticeable improvements other than a massive jump in benchRatioOf
:
❯ php -dopcache.enable_cli=1 ./vendor/bin/phpbench run --ref=original --retry-threshold=5 --iterations=10
PHPBench @git_tag@ running benchmarks...
with configuration file: /home/ocramius/Documents/moneyphp/money/phpbench.json
with PHP version 8.0.3, xdebug ❌, opcache ✔
\Benchmark\Money\NumberInstantiationBench
benchConstructorWithZeroIntegerAmount...R1 I0 - [Mo569.571μs vs Mo591.581μs] -3.72% (±1.94%)
benchConstructorWithPositiveIntegerAmou.R2 I8 - [Mo599.841μs vs Mo550.683μs] +8.93% (±2.41%)
benchConstructorWithNegativeIntegerAmou.R1 I4 - [Mo621.906μs vs Mo580.812μs] +7.08% (±2.40%)
benchConstructorWithZeroAndFractionalAm.R1 I9 - [Mo570.344μs vs Mo595.014μs] -4.15% (±2.62%)
benchConstructorWithFractionalAmount....R2 I3 - [Mo600.387μs vs Mo611.898μs] -1.88% (±2.04%)
benchConstructorWithNegativeFractionalA.R1 I2 - [Mo590.276μs vs Mo580.123μs] +1.75% (±1.99%)
\Benchmark\Money\MoneyOperationBench
benchAdd................................R1 I3 - [Mo999.916μs vs Mo987.689μs] +1.24% (±1.97%)
benchSubtract...........................R1 I9 - [Mo924.575μs vs Mo936.192μs] -1.24% (±2.18%)
benchMultiply...........................R3 I8 - [Mo992.857μs vs Mo1.057ms] -6.09% (±2.46%)
benchDivide.............................R1 I1 - [Mo1.015ms vs Mo1.031ms] -1.54% (±2.58%)
benchRatioOf............................R5 I8 - [Mo381.761μs vs Mo989.503μs] -61.42% (±1.89%)
benchMod................................R1 I9 - [Mo396.292μs vs Mo401.023μs] -1.18% (±2.16%)
benchIsSameCurrency.....................R2 I8 - [Mo4.000μs vs Mo2.000μs] +100.00% (±0.00%)
benchIsZero.............................R1 I3 - [Mo393.902μs vs Mo426.642μs] -7.67% (±1.72%)
benchAbsolute...........................R1 I4 - [Mo379.667μs vs Mo396.644μs] -4.28% (±2.79%)
benchNegative...........................R1 I3 - [Mo979.540μs vs Mo983.110μs] -0.36% (±2.10%)
benchIsPositive.........................R1 I4 - [Mo408.442μs vs Mo392.182μs] +4.15% (±2.21%)
benchCompare............................R1 I8 - [Mo381.159μs vs Mo397.301μs] -4.06% (±1.87%)
benchLessThan...........................R1 I6 - [Mo391.462μs vs Mo390.164μs] +0.33% (±1.71%)
benchLessThanOrEqual....................R4 I6 - [Mo416.380μs vs Mo430.164μs] -3.20% (±2.67%)
benchEquals.............................R3 I4 - [Mo4.000μs vs Mo3.000μs] +33.33% (±0.00%)
benchGreaterThan........................R1 I5 - [Mo382.789μs vs Mo390.450μs] -1.96% (±1.71%)
benchGreaterThanOrEqual.................R1 I1 - [Mo379.530μs vs Mo411.738μs] -7.82% (±1.33%)
\Benchmark\Money\MoneyInstantiationBench
benchConstructorWithZeroIntegerAmount...R2 I9 - [Mo945.877μs vs Mo898.483μs] +5.27% (±2.50%)
benchConstructorWithPositiveIntegerAmou.R1 I7 - [Mo887.787μs vs Mo937.671μs] -5.32% (±2.63%)
benchConstructorWithNegativeIntegerAmou.R3 I7 - [Mo958.738μs vs Mo909.286μs] +5.44% (±2.60%)
benchConstructorWithZeroStringAmount....R1 I0 - [Mo954.548μs vs Mo933.039μs] +2.31% (±2.40%)
benchConstructorWithPositiveStringAmoun.R3 I9 - [Mo931.642μs vs Mo857.589μs] +8.64% (±2.42%)
benchConstructorWithNegativeStringAmoun.R1 I2 - [Mo943.121μs vs Mo904.536μs] +4.27% (±1.88%)
Subjects: 29, Assertions: 0, Failures: 0, Errors: 0
Removed newInstance
private constructor: can be inlined where relevant
Also added an is_int()
special case to the constructor, since we often deal with
integer values when constructing a Money
instance, so we don't need to check for
a more expensive filter_var()
operation.
Simplified Money#equals()
to only check currency equality when amount equality is also non-matching
This moves away a function call that is otherwise repeated very often, and which can lead to a lot of runtime overhead for no reason.
Instead, we do this comparison only when the amount is the same (direct equality, faster for the engine).
Directly checking equality of two currencies at engine level
While calling Currency#equals(Currency)
may indeed look better from a domain perspective,
Currency
is final
, and currency comparison is one of the most frequent operations performed
on Money
(for internal assertions).
Therefore, removing the method call is both feasible and beneficial for performance:
❯ php -dopcache.enable_cli=1 ./vendor/bin/phpbench run --ref=original --retry-threshold=5 --iterations=10
PHPBench @git_tag@ running benchmarks...
with configuration file: /home/ocramius/Documents/moneyphp/money/phpbench.json
with PHP version 8.0.3, xdebug ❌, opcache ✔
\Benchmark\Money\NumberInstantiationBench
benchConstructorWithZeroIntegerAmount...R3 I7 - [Mo561.632μs vs Mo591.581μs] -5.06% (±3.01%)
benchConstructorWithPositiveIntegerAmou.R1 I7 - [Mo542.669μs vs Mo550.683μs] -1.46% (±1.00%)
benchConstructorWithNegativeIntegerAmou.R1 I2 - [Mo579.585μs vs Mo580.812μs] -0.21% (±1.60%)
benchConstructorWithZeroAndFractionalAm.R3 I8 - [Mo574.055μs vs Mo595.014μs] -3.52% (±1.86%)
benchConstructorWithFractionalAmount....R1 I9 - [Mo580.926μs vs Mo611.898μs] -5.06% (±2.09%)
benchConstructorWithNegativeFractionalA.R2 I8 - [Mo587.192μs vs Mo580.123μs] +1.22% (±2.55%)
\Benchmark\Money\MoneyOperationBench
benchAdd................................R1 I8 - [Mo985.200μs vs Mo987.689μs] -0.25% (±2.61%)
benchSubtract...........................R1 I8 - [Mo985.114μs vs Mo936.192μs] +5.23% (±2.70%)
benchMultiply...........................R1 I0 - [Mo988.329μs vs Mo1.057ms] -6.52% (±2.69%)
benchDivide.............................R1 I7 - [Mo933.611μs vs Mo1.031ms] -9.43% (±0.93%)
benchRatioOf............................R4 I4 - [Mo392.845μs vs Mo989.503μs] -60.30% (±1.70%)
benchMod................................R1 I3 - [Mo421.904μs vs Mo401.023μs] +5.21% (±1.72%)
benchIsSameCurrency.....................R2 I6 - [Mo1.000μs vs Mo2.000μs] -50.00% (±0.00%)
benchIsZero.............................R1 I7 - [Mo400.636μs vs Mo426.642μs] -6.10% (±1.00%)
benchAbsolute...........................R10 I9 - [Mo397.953μs vs Mo396.644μs] +0.33% (±2.76%)
benchNegative...........................R1 I6 - [Mo955.247μs vs Mo983.110μs] -2.83% (±2.45%)
benchIsPositive.........................R1 I0 - [Mo405.106μs vs Mo392.182μs] +3.30% (±2.71%)
benchCompare............................R3 I9 - [Mo401.284μs vs Mo397.301μs] +1.00% (±2.12%)
benchLessThan...........................R1 I9 - [Mo390.481μs vs Mo390.164μs] +0.08% (±1.84%)
benchLessThanOrEqual....................R1 I5 - [Mo395.329μs vs Mo430.164μs] -8.10% (±2.53%)
benchEquals.............................R10 I9 - [Mo1.000μs vs Mo3.000μs] -66.67% (±0.00%)
benchGreaterThan........................R1 I0 - [Mo414.980μs vs Mo390.450μs] +6.28% (±2.71%)
benchGreaterThanOrEqual.................R1 I1 - [Mo385.041μs vs Mo411.738μs] -6.48% (±2.64%)
\Benchmark\Money\MoneyInstantiationBench
benchConstructorWithZeroIntegerAmount...R1 I9 - [Mo954.935μs vs Mo898.483μs] +6.28% (±1.18%)
benchConstructorWithPositiveIntegerAmou.R1 I3 - [Mo913.027μs vs Mo937.671μs] -2.63% (±2.09%)
benchConstructorWithNegativeIntegerAmou.R1 I0 - [Mo926.714μs vs Mo909.286μs] +1.92% (±2.25%)
benchConstructorWithZeroStringAmount....R2 I9 - [Mo998.900μs vs Mo933.039μs] +7.06% (±2.79%)
benchConstructorWithPositiveStringAmoun.R2 I4 - [Mo927.877μs vs Mo857.589μs] +8.20% (±2.17%)
benchConstructorWithNegativeStringAmoun.R2 I9 - [Mo951.571μs vs Mo904.536μs] +5.20% (±2.64%)
Subjects: 29, Assertions: 0, Failures: 0, Errors: 0
Removed func_num_args()
magic method logic, replaced by inlined count()
operation that can be optimized by opcache
❯ php -dopcache.enable_cli=1 ./vendor/bin/phpbench run --ref=original --retry-threshold=5 --iterations=100 --filter=Avg
PHPBench @git_tag@ running benchmarks...
with configuration file: /home/ocramius/Documents/moneyphp/money/phpbench.json
with PHP version 8.0.3, xdebug ❌, opcache ✔
\Benchmark\Money\MoneyOperationBench
benchAvg................................R1 I63 - [Mo399.867μs vs Mo404.221μs] -1.08% (±2.29%)
Subjects: 1, Assertions: 0, Failures: 0, Errors: 0
PDF generation article update for 2023