How to check if an entered value is currency
How to check if an entered value is currency. Preferably by regular expression or php funct开发者_Go百科ion.
(values like 1550.50
, 1500
or 100.75
)
I guess what you really want is a way to tell any number from a number that makes sense as a currency value. So 1.04e-7
probably shouldn't match, and neither should 1.234
or 12.3
, even though all are of course numeric.
Finally, you'd have to expect thousands separators like 1,234.56
(which, like the decimal point, might also vary between locales). So, assuming that you only ever want to check currency values using the dot as decimal separator and the comma as an optional thousands separator, try this:
/\b\d{1,3}(?:,?\d{3})*(?:\.\d{2})?\b/
Explanation:
\b # word boundary assertion
\d{1,3} # 1-3 digits
(?: # followed by this group...
,? # an optional comma
\d{3} # exactly three digits
)* # ...any number of times
(?: # followed by this group...
\. # a literal dot
\d{2} # exactly two digits
)? # ...zero or one times
\b # word boundary assertion
I use this:
function isCurrency($number)
{
return preg_match("/^-?[0-9]+(?:\.[0-9]{1,2})?$/", $number);
}
//usage examples
echo (isCurrency("10.36") ? "TRUE" : "FALSE");
echo (isCurrency(10.3) ? "TRUE" : "FALSE");
Beware of:
this function accepts also negative currency values, if you don't want to accept them remove the
-?
that you find at the beginning of thepreg_match
this function returns
TRUE
also for values like13.7
(only one decimal), if you want the decimal to be always two than replace{1,2}
with{2}
(but prior doing this read point 3 below)this function returns
TRUE
also for values like0000.78
(more than one leading zero), but usually this kind of function is needed to filter value submitted by forms before inserting them into DB fields of typeDECIMAL(n.2)
. When inserting in these kind of fields MySQL accepts both0000.78
and13.7
as valid values in query, and auto converts them into0.78
and13.70
Based on Tim Pietzcker great answer above, I created:
/* Sample usage:
* ============
* echo '<ol>';
* echo '<li>', (isCurrency('10.36') ? "TRUE" : "FALSE"), '</li>'; // 1 - TRUE
* echo '<li>', (isCurrency('10.3') ? "TRUE" : "FALSE"), '</li>'; // 2 - TRUE
* echo '<li>', (isCurrency('10.') ? "TRUE" : "FALSE"), '</li>'; // 3 - TRUE
* echo '<li>', (isCurrency('10') ? "TRUE" : "FALSE"), '</li>'; // 4 - TRUE
* echo '<li>', (isCurrency('1,088,888,888,888') ? "TRUE" : "FALSE"), '</li>'; // 5 - TRUE
* echo '<li>', (isCurrency('1,088888,888,888') ? "TRUE" : "FALSE"), '</li>'; // 6 - I'm not sure if this should return TRUE or FALSE. For now going with TRUE as we can still interpret the desired value regardless whether the commas are correct.
* echo '<li>', (isCurrency('$10') ? "TRUE" : "FALSE"), '</li>'; // 7 - TRUE
* echo '<li>', (isCurrency('-10') ? "TRUE" : "FALSE"), '</li>'; // 8 - TRUE
* echo '<li>', (isCurrency('$-10') ? "TRUE" : "FALSE"), '</li>'; // 9 - TRUE
* echo '<li>', (isCurrency('-$10') ? "TRUE" : "FALSE"), '</li>'; // 10 - TRUE
* echo '<li>', (isCurrency('--$10') ? "TRUE" : "FALSE"), '</li>'; // 11 - FALSE
* echo '<li>', (isCurrency('-$$10') ? "TRUE" : "FALSE"), '</li>'; // 12 - FALSE
* echo '<li>', (isCurrency('10x') ? "TRUE" : "FALSE"), '</li>'; // 13 - FALSE
* echo '<li>', (isCurrency('x10') ? "TRUE" : "FALSE"), '</li>'; // 14 - FALSE
* echo '</ol>'; */
function isCurrency (string $currencyToTest): bool
{
$regExpPattern = '/^[$-]{0,2}\d{1,3}(?:,?\d{3})*(?:\.\d{0,2})?$/';
/* $regExpPattern explanation
/^ # string must begin with
[$-](0,2) # optional $ and/or -
\d{1,3} # 1-3 digits
(?: # followed by this group...
,? # an optional comma
\d{3} # exactly three digits
)* # ...any number of times
(?: # followed by this group...
\. # a literal dot
\d{2} # exactly two digits
)? # ...zero or one times
$/ # must end with
*/
$currencyToTest = trim ($currencyToTest);
return preg_match ($regExpPattern, $currencyToTest);
}
Added:
- Ability to prefix with $ and/or -.
- Added ability for no decimal points as in $4.
- Value to test must be alone in parm.
Without Tim Pietzcker response, not sure I would have gotten this far.
You can't be sure. The user might be thinking of chickens. You need to check if the user entered a float. Have a look at preg_match: http://jp2.php.net/manual/en/function.preg-match.php
You also need to ask yourself if you want to try to work with what the user entered, or if you want to reject it and only accept an exact format.
I quickly spun up a function for checking if a string or int is a valid price and if not, converting it. The final output is always going to be a string with two digits after the decimal, like 1000.00
.
It removes minus/negative signs, commas, spaces, and dollar signs. The only except is when if the string contains any characters like letters that would set is_numeric()
to false.
Here is the function:
function convertToValidPrice($price) {
$price = str_replace(['-', ',', '$', ' '], '', $price);
if(!is_numeric($price)) {
$price = null;
} else {
if(strpos($price, '.') !== false) {
$dollarExplode = explode('.', $price);
$dollar = $dollarExplode[0];
$cents = $dollarExplode[1];
if(strlen($cents) === 0) {
$cents = '00';
} elseif(strlen($cents) === 1) {
$cents = $cents.'0';
} elseif(strlen($cents) > 2) {
$cents = substr($cents, 0, 2);
}
$price = $dollar.'.'.$cents;
} else {
$cents = '00';
$price = $price.'.'.$cents;
}
}
return $price;
}
And here is to test it:
var_dump(convertToValidPrice('100')); // 100.00
var_dump(convertToValidPrice('-100')); // 100.00
var_dump(convertToValidPrice(100)); // 100.00
var_dump(convertToValidPrice('$100')); // 100.00
var_dump(convertToValidPrice('100.98')); // 100.98
var_dump(convertToValidPrice('100.9')); // 100.90
var_dump(convertToValidPrice('100.')); // 100.00
var_dump(convertToValidPrice('1,00.98')); // 100.98
var_dump(convertToValidPrice('1,000.98')); // 1000.98
var_dump(convertToValidPrice('100.98829382')); // 100.98
var_dump(convertToValidPrice('abc')); // null
精彩评论