When I started writing this post I wasn’t sure should I put this into programming category or fun … I mean, validating if passed variable is integer aka whole number, how hard can it be? It appears not really easy in PHP 🙂
First off some background, I needed to validate an array with db key values (like array(1,2,6,7,…n)), so I thought of using simple function like array_filter with callback, something like:
array_filter($foo_array, 'is_int');
where is_int is callback, calling built in is_int function for each array value in order to filter out non int values.
The problem is (yes after 10 years dealing with PHP I am aware of that), PHP doesn’t treat int and string numbers the same, so string ’42’ wouldn’t be recognized as integer.
is_int('42'); //false
is_int(42); //true
To make things more “interesting” for programmers, if you have integer form data like age, year or whatever, they will be sent trough $_POST/$_GET/$_REQUEST arrays as ‘string numbers’ (so string ’42’ not int 42).
There is nice function to deal with such things and it’s name is is_numeric … but it only checks if string is actually number, so float values will be evaluated to true as well. ctype_digit on the other hand is opposite of is_int, it will only return true if test variable is string number, so ’42’ would evaluate to true, but 42 to false.
ctype_digit('42'); //true
ctype_digit(42);//false
And to make things even worse, PHP is silently converting really big integers to float (those bigger than PHP_INT_MAX const) so guess what would you get for number like is_int(23234234234235334234234)? Yep, false 🙂
$var = PHP_INT_MAX;
var_dump($var++); //true
var_dump($var); //false it's float now!
Yeah I know, you could cast var to int and do is_int … or cast var to string and do ctype_digit … and other dirty hacks… but what if someone smart from PHP team had decided to let say add 2nd argument to is_int check so you can check for type in some kind of ‘non strict’ mode, so string ’42’ is actually evaluated as integer? Something like this in C I guess:
function is_int(int var, int strict = 1)
{
//if strict is false evaluate string integers like '42' to true!
}
All in all (at least to me), the easiest way to validate whether a variable is whole number (aka string or integer string) is with regular expression. Something like this:
/**
* Test if number is integer, including string integers
* @param mixed var
* @return boolean
*/
function isWholeNumber($var)
{
if(preg_match('/^\d+$/', $var))
{
return true;
}
else
{
return false;
}
}
Someone from PHP dev team should really consider fixing this.