tags:

views:

146

answers:

5

PHP has many built-in functions to validate numbers but they all expect input in computer format: 1234.56. I need to validate stuff like 1,234.56 (English) or 1.234,56 (Spanish), together with some typical attributes (accepted range, max number of decimals, etc.).

I started writing my own function but I soon got lost. It's easy to read the user input into a float variable but I want to be able to detect numbers with invalid formats like 1,23456.7 or 1..25.

Do you have any recommendation on the subject?

(Decimal and thousand characters are known beforehand and it's okay to hard-code digit groups as three, there's no need to cover Indian number format.)

A: 

You perform all your calculations and for the result variable, you could use the built-in function number_format to format it as per your requirements.

Sarfraz
I don't want to convert from float to string. I want to validate whether a string contains a valid number in national format. `12.345` is a valid number but I can't store it in a DECIMAL(4,2) column. `1000` is a valid number but not a valid discount.
Álvaro G. Vicario
+1  A: 

I found an interesting function in a comment in the php manual : http://fr2.php.net/manual/en/language.types.float.php#92885 Have a look.

greg0ire
Although not applied directly to my problem, it's a witty approach. Too bad I got scared of setlocale() after suffering from some bugs in the Windows implementation.
Álvaro G. Vicario
+1  A: 

You can use regular expressions to validate numbers:

$ds = '.'; // Decimal separator
$ts = ','; // Thousand separator

$isValidFloat = preg_match(
    '/^

         # Integer part, one of the two allowed formats:
         # 1) with thousand separator, grouped by 3 digits
         # 2) without thousand separator
         (\d{1,3}(' . preg_quote($ts) . '\d{3})* | \d+)

         # Optional decimal part
         (' . preg_quote($ds) . '\d+)?

    $/x', $string);

And convert it to a float like this:

$float = (float) strtr($string, array($ts => '', $ds => '.'));
Alexander Konstantinov
+2  A: 

Check out NumberFormatter::parse. You can parse numbers in a lot of locales with it. The whole intl extension is useful, even though it is not quite "there" yet.

janmoesen
Unfortunately, works only in PHP 5.3+, but nice solutions anyways, didn't know about it.
Alexander Konstantinov
This is not the case, but I sometimes build Windows-only apps where I control the PHP version that's installed. I'll take this into account.
Álvaro G. Vicario
+1  A: 

In addition to the given solutions, I'd recommend the PEAR Validation package for validating numbers.

Here's an example from their site:

<?php
require_once 'Validate.php';

$number = '-8,1';
if (Validate::number($number,
    array('decimal' => '.,', 'min' => -9, 'max' => -7 ))) {
    echo 'Valid';
} else {
    echo 'Invalid';
}

If you want to be stricter on the format then you could parse it as a float (which you have done), and then use number_format to output the float into the formats you accept, and try to match the original format against any of the ones you have generated.

mqchen
I'll have a look at it.(It's better not to be so strict: for me, `1000.5` is as valid as `1,000.50`.)
Álvaro G. Vicario