The Goal
The original question is about validating a value of unknown data type and discarding all values except those that contain nothing but digits. There seems to be only two ways to achieve this desired result.
If the goal is to fail fast, one would want to check for invalid values and then fail rather than checking for valid values and having to wrap all code in an if
block.
Option 1 from Question
if (preg_match('/D/', $company_id)) exit('Invalid parameter');
Using regex
to fail if match non-digits. Con: regex engine has overhead
Option 2 from Question
if (!ctype_digit((string) $company_id)) exit('Invalid parameter');
Using ctype_digit
to fail if FALSE. Con: value must be cast to string which is a (small) extra step
You must cast value to a string because ctype_digit
expects a string and PHP will not cast the parameter to a string for you. If you pass an integer to ctype_digit
, you will get unexpected results.
This is documented behaviour. For example:
ctype_digit('42'); // true
ctype_digit(42); // false (ASCII 42 is the * character)
Difference Between Option 1 and 2
Due to the overhead of the regex engine, option two is probably the best option. However, worrying about the difference between these two options may fall into the premature optimization category.
Note: There is also a functional difference between the two options above. The first option considers NULL
and empty strings as valid values, the second option does not (as of PHP 5.1.0). That may make one method more desirable than the other. To make the regex
option function the same as the ctype_digit
version, use this instead.
if (!preg_match('/^d+$/', $company_id)) exit('Invalid parameter');
Note: The 'start of string' ^
and 'end of string' $
anchors in the above regex
are very important. Otherwise, abc123def
would be considered valid.
Other Options
There are other methods that have been suggested here and in other questions that will not achieve the stated goals, but I think it is important to mention them and explain why they won't work as it might help someone else.
is_numeric
allows exponential parts, floats, and hex values
is_int
checks data type rather than value which is not useful for validation if '1'
is to be considered valid. And form input is always a string. If you aren't sure where the value is coming from, you can't be sure of the data type.
filter_var
with FILTER_VALIDATE_INT
allows negative integers and values such as 1.0
. This seems like the best function to actually validate an integer regardless of data type. But doesn't work if you want only digits. Note: It's important to check FALSE
identity rather than just truthy/falsey if 0
is to be considered a valid value.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…