I'm working on a PHP application. I need to validate that a string is useable as a currency value. I would like the following to validate:
$5.00
5
5.00
£5.00
I want the pattern to be liberal enough to accept a reasonable string. I would also like it to accept an currency symbol; however, to validate currency, it can be any character or characters because I'll ultimately store the value as a two decimal float. So, '$5.00' or 'USD 5.00' would become '5.00' when stored in the database. I'm currently using the following:
preg_match('/^[0-9]*\.?[0-9]+$/',$value)
It works for "5" or "5.00", but it does not account for the currency symbol. How do I adjust this to allow for the currency symbol?
Thank you!
EDIT: According to a comment below, it looks like my regex will allow too many decimals. Can you also help me sort out that issue?
To allow all currency symbols you will need to use Unicode Character Properties
\p{Sc}
or \p{Currency_Symbol}
: any currency sign.
Try with this one:
$value=preg_replace('/^(\p{Sc}?\d*)((\.|,)\d\d\d)?\d*$/u','$1$2',$value);
But if you are expecting the number from an input, will be better make a form where the user specify the currency from a selectable list, and just take care whether the user will only introduce numbers, that's how PAYPAL does.
A regex monstrosity follows:
/^(?<currency_left>\p{Sc}|[A-Z]{3})?\s*
(?<amount>(?:(?!,)[,\d]*)(?:(?=.\d)|(?<=\d))(?:\.\d*)?)\s*
(?<currency_right>(?(currency_left)|(?:\p{Sc}|[A-Z]{3})))?$/ui
(\p{Sc} matches any currency symbol.)
This will match an optional 3-digit currency symbol or code, followed by a positive number, followed by a currency symbol or 3-digit code. The number may include a decimal, or commas before the decimal. The currency symbol can appear before or after the number, but not both. The group Amount stores the decimal part, and currency_left and currency_right the currency part (currency_left and currency_right will not both match).