Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

of

How to count money using PHP and not lose money Slide 1 How to count money using PHP and not lose money Slide 2 How to count money using PHP and not lose money Slide 3 How to count money using PHP and not lose money Slide 4 How to count money using PHP and not lose money Slide 5 How to count money using PHP and not lose money Slide 6 How to count money using PHP and not lose money Slide 7 How to count money using PHP and not lose money Slide 8 How to count money using PHP and not lose money Slide 9 How to count money using PHP and not lose money Slide 10 How to count money using PHP and not lose money Slide 11 How to count money using PHP and not lose money Slide 12 How to count money using PHP and not lose money Slide 13 How to count money using PHP and not lose money Slide 14 How to count money using PHP and not lose money Slide 15 How to count money using PHP and not lose money Slide 16 How to count money using PHP and not lose money Slide 17 How to count money using PHP and not lose money Slide 18 How to count money using PHP and not lose money Slide 19 How to count money using PHP and not lose money Slide 20 How to count money using PHP and not lose money Slide 21 How to count money using PHP and not lose money Slide 22 How to count money using PHP and not lose money Slide 23 How to count money using PHP and not lose money Slide 24 How to count money using PHP and not lose money Slide 25 How to count money using PHP and not lose money Slide 26 How to count money using PHP and not lose money Slide 27 How to count money using PHP and not lose money Slide 28 How to count money using PHP and not lose money Slide 29 How to count money using PHP and not lose money Slide 30 How to count money using PHP and not lose money Slide 31 How to count money using PHP and not lose money Slide 32 How to count money using PHP and not lose money Slide 33 How to count money using PHP and not lose money Slide 34 How to count money using PHP and not lose money Slide 35 How to count money using PHP and not lose money Slide 36
Upcoming SlideShare
What to Upload to SlideShare
Next
Download to read offline and view in fullscreen.

1 Like

Share

Download to read offline

How to count money using PHP and not lose money

Download to read offline

Introduction to the MoneyPHP library and description of different issues caused by using FLOAT type to handle monetary amounts.

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

How to count money using PHP and not lose money

  1. 1. How to count money and not lose it Piotr Horzycki www.peterdev.pl | twitter.com/peterdevpl
  2. 2. var_dump((int) ('4.20' * 100)); → int(420) var_dump((int) ('4.10' * 100)); → int(409) “I can set a product price to 4.20 PLN, but not 4.10 – it’s being changed to 4.09. Why?” Bugs...
  3. 3. if (parseInt(amount) > 0) { /* proceed with payment */ } else { /* disable payment button */ } Why does 0.5 not work? Bugs...
  4. 4. <p>Price: <?php echo strtr($price, '.', ','); ?> PLN</p> <p>Price: <?php echo str_replace($price, '.', ','); ?> PLN</p> <p>Price: <?php echo number_format($price, 2, ',', ' '); ?> PLN</p> Formatting price strings – the wrong way...
  5. 5. “A large proportion of the computers in this world manipulate money, so it's always puzzled me that money isn't actually a first class data type in any mainstream programming language. The lack of a type causes problems, the most obvious surrounding currencies. (...) The more subtle problem is with rounding. Monetary calculations are often rounded to the smallest currency unit. When you do this it's easy to lose pennies (or your local equivalent) because of rounding errors. The good thing about object-oriented programming is that you can fix these problems by creating a Money class that handles them. Of course, it's still surprising that none of the mainstream base class libraries actually do this.” https://martinfowler.com/eaaCatalog/money.html
  6. 6. use MoneyCurrency; use MoneyMoney; // 5,00 USD $fiver = new Money(500, new Currency('USD')); // or shorter: $fiver = Money::USD('500'); MoneyPHP: PHP implementation of the Money pattern
  7. 7. final class Money implements JsonSerializable { /** @var string */ private $amount; /** @var Currency */ private $currency; /** @var Calculator */ private static $calculator; private static $calculators = [ BcMathCalculator::class, GmpCalculator::class, PhpCalculator::class, ]; /* … */ }
  8. 8. $value1 = Money::EUR(800); $value2 = Money::EUR(500); $value3 = Money::EUR(100); $value1->add($value2); $value1->subtract($value2, $value3); $value1->multiply(2); $value1->divide(2); $value1->mod($value2); // 3.00 EUR $value1->ratioOf($value2); // '1.6' Basic money arithmetics
  9. 9. $value1 = Money::USD(800); // $8.00 $value2 = Money::USD(100); // $1.00 $result = $value1->isSameCurrency($value2); // true $result = $value1->equals($value2); // false $result = $value1->greaterThan($value2); // true Comparing money objects
  10. 10. Immutability $jimPrice = $hannahPrice = Money::EUR(2500); $coupon = Money::EUR(500); // wrong $jimPrice->subtract($coupon); $jimPrice->equals($hannahPrice); // true
  11. 11. Immutability $jimPrice = $hannahPrice = Money::EUR(2500); $coupon = Money::EUR(500); // wrong $jimPrice->subtract($coupon); $jimPrice->equals($hannahPrice); // true // correct $jimPrice = $jimPrice->subtract($coupon); $jimPrice->lessThan($hannahPrice); // true $jimPrice->equals(Money::EUR(2000)); // true $jimPrice and $hannahPrice are immutable value objects
  12. 12. use MoneyMoney; $profit = Money::EUR(5); // 5 euro cents list($my_cut, $investors_cut) = $profit->allocate([70, 30]); // $my_cut is 4 cents, $investors_cut is 1 cent Allocating profits
  13. 13. use MoneyMoney; $profit = Money::EUR(5); // 5 euro cents list($my_cut, $investors_cut) = $profit->allocate([70, 30]); // $my_cut is 4 cents, $investors_cut is 1 cent // The order is important: list($investors_cut, $my_cut) = $profit->allocate([30, 70]); // $my_cut is 3 cents, $investors_cut is 2 cents Allocating profits
  14. 14. Database INT, BIGINT… VARCHAR... DECIMAL (MySQL) NUMERIC (Oracle) FLOAT, DOUBLE...
  15. 15. Database INT, BIGINT… VARCHAR... DECIMAL (MySQL) NUMERIC (Oracle) FLOAT, DOUBLE... DECIMAL(10, 2) total decimal digits places max 99,999,999.99
  16. 16. Exchange rates... https://www.bankofengland.co.uk/boeapps/database/Rates.asp
  17. 17. https://en.wikipedia.org/wiki/Redenomination
  18. 18. https://www.theguardian.com/world/2018/aug/20/venezuela-bolivars-hyperinflation-banknotes
  19. 19. https://www.amusingplanet.com/2018/08/hungarys-hyperinflation-worst-case-of.html Hungary’s hyperinflation in 1946
  20. 20. Converting currencies with MoneyPHP use MoneyConverter; use MoneyCurrency; use MoneyExchangeFixedExchange; $exchange = new FixedExchange([ 'EUR' => [ 'USD' => 1.25 ] ]); $converter = new Converter(new ISOCurrencies(), $exchange); $eur100 = Money::EUR(100); $usd125 = $converter->convert($eur100, new Currency('USD'));
  21. 21. Converting currencies with MoneyPHP and Swap use MoneyMoney; use MoneyConverter; use MoneyExchangeSwapExchange; use SwapBuilder; $swap = (new Builder()) ->add('fixer', ['access_key' => 'your-access-key']) ->build(); $exchange = new SwapExchange($swap); $converter = new Converter(new ISOCurrencies(), $exchange); $eur100 = Money::EUR(100); $usd125 = $converter->convert($eur100, new Currency('USD'));
  22. 22. Save the conversion rate!
  23. 23. <p>Price: <?php echo strtr($price, '.', ','); ?> PLN</p> <p>Price: <?php echo str_replace($price, '.', ','); ?> PLN</p> <p>Price: <?php echo number_format($price, 2, ',', ' '); ?> PLN</p> Price formatting again...
  24. 24. $100 €100 £100 ¥100 ... Price formatting again...
  25. 25. $100 €100 £100 ¥100 ... 100 zł Price formatting again...
  26. 26. $money = new Money(100, new Currency('USD')); $currencies = new ISOCurrencies(); $numberFormatter = new NumberFormatter( 'en_US', NumberFormatter::CURRENCY ); $moneyFormatter = new IntlMoneyFormatter( $numberFormatter, $currencies ); echo $moneyFormatter->format($money); // outputs $1.00
  27. 27. $money = new Money('12345678', new Currency('PLN')); $currencies = new ISOCurrencies(); $numberFormatter = new NumberFormatter( 'pl_PL', NumberFormatter::CURRENCY ); $moneyFormatter = new IntlMoneyFormatter( $numberFormatter, $currencies ); echo $moneyFormatter->format($money); // outputs 123 456,78 zł
  28. 28. https://en.wikipedia.org/wiki/Dollar_sign
  29. 29. $currencies = new ISOCurrencies(); $americanNumberFormatter = new NumberFormatter('en_US', NumberFormatter::CURRENCY); $mexicanNumberFormatter = new NumberFormatter('es_MX', NumberFormatter::CURRENCY); $dollarsFormatter = new IntlMoneyFormatter($americanNumberFormatter, $currencies); $pesosFormatter = new IntlMoneyFormatter($mexicanNumberFormatter, $currencies); $dollars = new Money(12345, new Currency('USD')); $pesos = new Money(12345, new Currency('MXN')); echo $dollarsFormatter->format($dollars) . PHP_EOL; // $123.45 echo $pesosFormatter->format($pesos); // $123.45 Be careful with parsing money strings!
  30. 30. Rounding ● https://en.wikipedia.org/wiki/Cash_rounding (aka Swedish rounding) ● Polish income tax: round to the nearest whole zloty
  31. 31. Rounding $money = new Money('12345', new Currency('USD')); // $123.45 is the initial amount $multiplied = $money->multiply('1.23', Money::ROUND_UP); // $151.8435 before rounding echo $dollarsFormatter->format($multiplied); // output: $151.85
  32. 32. Architecture final class Invoice { private $seller; private $buyer; private $issueDate; private $dueDate; /* … */ public addItem(Money $unitPrice, int $quantity, Tax $tax) {} public getTotalAmount(): Money {} public getTaxAmount(): Money {} }
  33. 33. Architecture interface InvoiceBuilder { fromSeller(Contractor $seller): self; toBuyer(Contractor $buyer): self; addItem(Money $unitPrice, int $quantity, Tax $tax): self; /* … */ build(): Invoice; }
  34. 34. Further reading ● https://www.h-schmidt.net/FloatConverter/IEEE754.html ● https://martinfowler.com/eaaCatalog/money.html ● http://moneyphp.org/en/stable/ ● https://romaricdrigon.github.io/2019/07/05/value-objects-doctrine-and-symfony-forms ● https://github.com/Sylius/SyliusMoneyBundle
  35. 35. Thank you! Piotr Horzycki www.peterdev.pl | twitter.com/peterdevpl
  • asilvino

    Oct. 28, 2020

Introduction to the MoneyPHP library and description of different issues caused by using FLOAT type to handle monetary amounts.

Views

Total views

1,014

On Slideshare

0

From embeds

0

Number of embeds

4

Actions

Downloads

1

Shares

0

Comments

0

Likes

1

×