Validating numbers with PHPValidating numbers with PHP

Posted November 25th, 2008 in PHP

Last week David Walsh posted about validating numeric values and digits with PHP on his excellent blog. I posted my own comments about his particular post but they never appeared so I decided to post a better response here.

The point of David's post was that he needed to be able to validate between finding a numeric value (which might be a floating point number and therefore contain a decimal point) and whether a number only contains digits.

His solution was this:

/* numeric, decimal passes */
function validate_numeric($variable)
{
    return is_numeric($variable);
}

/* digits only, no dots */
function is_digits($element)
{
    return !preg_match ("/[^0-9]/", $element);
}

As I noted in my comment (which wasn't published), I'm not sure why you'd wrap is_numeric() into his validate_numeric() function when all it's doing is calling is_numeric(). Why not just call is_numeric() instead?

The is_digits() function on the other hand is actually pretty good. I initially thought there may be some issues with it but it works nicely but there is one simpler alternative.

is_integer - no good

In my comment I suggested that he could use the is_integer() function as long as the acceptable value was within the integer type range, and postive and negative values are acceptable. Of course, a digit only value might not be within the integer range, for example is_integer(12345678901234567890) would return false but does only contain numbers.

The problem with my initial assumption is that in PHP data submitted from a form that *does* only contain digits and *is* within the integer range will still return false from is_integer() because it will be considered to be a string. For example:

<form ...>
<input type="text" name="foo" value="123" />
</form>

And then doing this when the form is submitted:

echo (int)is_integer((int)$_POST['foo']);

will print 0, meaning false. D'oh! Also an integer can contain - if it is a negative value so -123 will return true even though it contains more than just digits.

ctype_digit - not much better

The other alternative is the ctype_digit() function which saves having to mess around with regular expressions. ctype_digit checks if all of the characters in the passed in value are numerical. Only the numbers 0 to 9 are valid, and it doesn't matter if the value is type cast as a string, which is what will happen from a form post.

However, ctype_digit it expects the input to be a string and will return false if the value passed in is an ineteger...

For example:

var_dump(ctype_digit(123));
var_dump(ctype_digit('123'));
var_dump(ctype_digit(12345678901234567890));
var_dump(ctype_digit('12345678901234567890'));

These display:

bool(false)
bool(true)
bool(false)
bool(true)

You should be able to use (string), strval() etc to cast the value as a string first and then pass it to ctype_digit but I've found if the number is too large it still doesn't work.

For example, the first four below return true, but the last one returns false:

ctype_digit(strval(12345678901));
ctype_digit(strval(123456789012));
ctype_digit(strval(1234567890123));
ctype_digit(strval(12345678901234));
ctype_digit(strval(123456789012345));

Use the regexp

So my initial thought was just use is_integer() and someone else suggested to use ctype_digit but it would turn out that using the regular expression with preg_match is the best solution after all. Just remember when using regular expressions with PHP to use the preg* functions and not the ereg* functions because the latter are deprecated in PHP 6.

Related posts:

Share or Bookmark

Share or Bookmark this page using the following services. You will need to have an account with the selected service in order to post links or bookmark this page.

Subscribe or Follow

Subscribe via RSS or email, or follow me on Facebook or Twitter below. The RSS icon takes you through to Feedburner where you can select the service or application to use.

Comments

blog comments powered by Disqus