brick / money

A money and currency library for PHP
MIT License
1.61k stars 96 forks source link

Formatting the Number part in toString or add formatting functions #19

Closed mtangoo closed 6 years ago

mtangoo commented 6 years ago

Hi, Is there a way to format string echo-ed? I meanis echo Money::of(5000, 'TZS') should display TZS 5,000.00 instead of current TZS 5000.00. It makes reading big number easier.

PHP have already number formatting function and it wouldn't be very hard to add its.

I'm not sure if every currency have corresponding separator or even if there is such a thing as universal separator. If indeed there is separator per currency we can check the currency and apply number_format accordingly. If not, then we can add a format($separator=',') function to money class that works the same as toString() but formats the number part of the result.

What do you think?

BenMorel commented 6 years ago

Hi, first of all __toString() does not do any formatting on purpose, it always outputs the currency code and the raw amount in a format that would be easy to parse by a machine, yet be readable by a human.

As regards to formatting, the library currently offers two formatting functions:

The output with the en_TZ locale is close to what you're after:

$money = Money::of(5000, 'TZS');
echo $money->formatTo('en_TZ'); // TSh5,000.00

If you're not happy with the result, you can configure a NumberFormatter and use the second option:

$money = Money::of(5000, 'TZS');
$formatter = new \NumberFormatter('en_TZ', \NumberFormatter::CURRENCY);
$formatter->setSymbol(\NumberFormatter::CURRENCY_SYMBOL , 'TZS ');
$formatter->setAttribute(\NumberFormatter::MIN_FRACTION_DIGITS, 2);
echo $money->formatWith($formatter); // TZS 5,000.00

Does that fit your need?

mtangoo commented 6 years ago

Thanks for explanations that makes sense. I suggest you add that on documentation too.

On other hand, I think there's a need to have a formatting function that doesn't involve locale. The reason is, you don't always have locale especially for multi-nation apps. But even in that case you need formatting

I suggest formatSimple($separator) for simple formatting that doesn't require locale

BenMorel commented 6 years ago

I will definitely add this to the doc, you're right.

Regarding a generic formatting function: this is a complicated matter as there are so many variables to formatting (see the list of configurations possible in NumberFormatter to get an idea!) so I prefer not to open this can of worms for now.

At the moment formatWith() can do pretty much anything you want. Sure, it does force you to pass a locale, but it allows you to override pretty much everyting the locale defaults to (thousands separator, decimal separator, currency symbol, and many others). This may feel hackish, but I think that it should cover most use cases for now.

I'll be happy to revisit this is someone comes up with a real life use case for such a method, though.

BenMorel commented 6 years ago

Added doc: https://github.com/brick/money#formatting

I'm closing this issue for now, please feel free to comment if you have a real life use case that could not easily be solved with formatWith() 👍

mtangoo commented 6 years ago

I just gave a problem am facing right now that needs simple thousands separator. It's pretty common usage with projects that deal with money

Rather than going around hacking formatter to override all locale stuffs, it's better to do that manually, as it adds fewer lines of code.

Extending Money and adding that should not hurt :)

Cheers

VasekPurchart commented 6 years ago

I agree with Ben here, there is no such thing as "simple locale formatting", everyone expects the simple form to look differently and also two resulting number strings can mean different things for people expecting different locales (for example decimal comma vs thousands separator comma).

So it is best addressed by the applications author by either passing the users locale or picking a locale for the whole application (or a custom number formatter).

mtangoo commented 6 years ago

@Vasek, I didn't put word locale at all :) Actually there's simple formatter for numbers to make them readable and have nothing to do with locale. PHP includes one so at least it exists.

I was suggesting that the library handles that too. But since it seems a bad idea, I will extend Money class and add it there, problem solved!

The library already offers a lot for free and would not complain if such simple thing is missing

Cheers!

BenMorel commented 6 years ago

Yes, the matter is a whole lot more complicated than just thousands separator; this alone may solve your use case, but only yours; someone else may have different requirements!

Feel free to extend Money, though ;)

mtangoo commented 6 years ago

@BenMorel

Feel free to extend Money, though ;)

The class is final, so cannot be extended :)

BenMorel commented 6 years ago

True, then you should create a MoneyFormatter class :)