moneyphp / money

PHP implementation of Fowler's Money pattern.
http://moneyphp.org
MIT License
4.6k stars 440 forks source link

Storing a Free object #649

Closed hubertnnn closed 3 years ago

hubertnnn commented 3 years ago

For one of my projects I need a way to define something as free. The problem we have is how to do it using MoneyPHP. So far we checked a few ways and each have its own problems:

  1. Store Free as some currency eg Free = 0 USD. This has the problem when comparing with other currency eg is 10 EUR > Free? This will fail because it will compare 10 EUR > 0 USD and EUR =/= USD
  2. Store a free value for each currency. This way I can define something as being Free in dollars and another thing as being free in euros. Obviously this is causing a mess when it comes to managing that content and its very not user friendly to admins and end users.
  3. Store Free as NULL This solution is a bit more problematic because now I have to create my own calculator that accepts nullable Money objects and handle the nullable state each time.

Is there a standard way to store Free using Money object? And if not maybe we should add one. For example skip currency comparation if one of the values is equal to zero. Or even define a pseudo-currency for storing free value that can only be paired with value equal to zero and will not cause an exception in assertSameCurrency

UlrichEckhardt commented 3 years ago
  1. Add an exception to the comparison code that comparisons with zero ignore the currency?

Zero apples are indeed equal to zero oranges, so that might even work without introducing any weird/unexpected behaviour.

frederikbosch commented 3 years ago

Storage is outside of this libraries purpose. We cannot assume that zero apples is always zero oranges. A money object with zero amount can also be the result of a calculation (divide, multiply, add, subtract), and therefore we must always compare with currencies. The only thing I see that we could (!) consider is an equalsOrNone method that can be used for comparison.

frederikbosch commented 3 years ago

Since I do not consider this a bug, and this feature request is only to be considered in the form of a PR, I will close this until there is a PR to be discussed.

sagikazarmark commented 3 years ago

I think storage is not really a concern of this issue (despite the title).

This is an interesting problem and comes down to whether the 0 something = nothing statement is true or not.

On the implementation level, I tend to say that it's not because it would affect literally every calculation of this library.

For example: 0 EUR + 30 USD = ?

Or even better 30 USD + 0 EUR = ?

I think what I'm missing here as a justification is a scenario where you would compare different currencies in the first place. With other words: why would you handle free objects differently from non-free objects?

For example, in an ecommerce site supporting multiple currencies: when you select a currency, every price will be in that currency. Converting 0 EUR to 0 USD is trivial, but you would convert everything anyway, so why would you handle zero values differently?