0

I was using is_numeric to validate integers coming from POST data like:

if( ! is_numeric($_POST['integer_string'])) return FALSE // not a integer

Then I discovered is_numeric will return TRUE if the value has a decimal.

Next I tried casting and is_int:

$int = (int) $_POST['numeric_string'];
if( ! $int)  return FALSE // not a integer

But casting will cut the integer after a non numeric value is passed.

$int = '222i2';
echo $int;
// 222

The integer I'm attempting to validate will be used in WHERE clauses in SQL to identify integer primary keys.

What is a fool proof way to validate an integer from POST data or how do you personally deal with this problem?

5
  • There's many dupes. I've chosen php validate integer because it contains two decent answers: regular expressions and filter_input(). Commented Nov 4, 2013 at 16:28
  • ctype_digit Commented Nov 4, 2013 at 16:29
  • I viewed a lot of other answers, but none of them specified the integer being a primary key. But I suppose it's not that different from other integers. Commented Nov 4, 2013 at 17:10
  • That doesn't really matter. The only thing that makes the integer more risky compared to others is the usage within an SQL statement. That's why I included the note about prepared statements in my answer. Commented Nov 4, 2013 at 17:21
  • A primary key can be any data type supported by the database engine. It can also contain more than one column. There's nothing in the PK concept that makes it synonym for integer. Commented Nov 4, 2013 at 17:24

3 Answers 3

2

A fool proof way to validate anything in PHP are filter_var() and filter_input(). Plus of course using prepared statements either with PDO or MySQLi.

For your specific use case:

<?php

$id = filter_input(
    INPUT_POST,            // Submitted via $_POST
    "integer_string",      // Offset name in $_POST
    FILTER_VALIDATE_INT,   // The validation method
    FILTER_REQUIRE_SCALAR  // NULL and empty aren't valid
);

if ($id === false) {
    throw new InvalidArgumentException("Not an int!");
}

// Assuming you have a Database object that wraps your DB stuff.
$database->query("SELECT * FROM `table` WHERE `id` = ? LIMIT 1", "d", [ $id ]);

?>

If your PHP version doesn't support the various filter functions do the following:

<?php

if (ctype_digit($_POST["integer_string"]) === false) {
    throw new InvalidArgumentException;
}

// Before PHP 5.1.0
if (empty($_POST["integer_string"]) || ctype_digit($_POST["integer_string"]) === false) {
    throw new InvalidArgumentException;
}

?>
Sign up to request clarification or add additional context in comments.

Comments

2

PHP has filter input

http://www.php.net/manual/en/function.filter-input.php

which you can use with FILTER_VALIDATE_INT

2 Comments

filter_input() isn't unit testable, but one can use filter_var() if unit testing is important.
This is what I was looking for, thanks. Unit testing is not a problem 'cause I-just-dont-do-it
0

For php < 5.2 you can use a regular expression:

preg_match("/^[0-9]+$/", $_POST["integer_string"]);

http://php.net/manual/en/function.preg-match.php

3 Comments

Never use regular expressions for type validation!
@Fleshgrinder - Why not?
Use the right tool for the job and this is the wrong tool for the job. Of course the regular expression is correct (and I didn't say that it isn't). Plus, regular expressions have their use cases in validation code, but only to validate stuff you couldn't validate in another way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.