Make Sure Those Passed IDs Contain Numbers

When passing row IDs between pages, it's a good idea to check the value is what you expect. Values which could be tampered with by the user need to validated and sanitized. So, if an ID is supposed to be a number, we should make sure it is before running the database query. Let's discuss some options for checking for numbers.

Background

Let's say we have a page which displays product information based on an ID that's passed using the GET method. The following code retrieves the ID:

<?php
$product_id = (isset($_GET['id'])) ? $_GET['id'] : '';
?>

Basically, if the GET variable was set, it's assigned to our variable ($product_id). Otherwise, the variable is set to be blank. Now, to make sure the ID is a number.

Using Regular Expressions

For the longest time, regular expressions were my method of choice.

<?php
if(preg_match('~^\d+$~', $product_id)) {
    //it's a number, process query
} else {
    //not a number, display error
}
?>

The above regular expression works great, but it seems like there should be a simpler way. One that doesn't require the extra overhead of regular expressions.

Using is_numeric()

The is_numeric() function could be used for checking numbers, just keep in mind what the function actual considers to be a number. For example, the following cases evaluate to true:

<?php
is_numeric('9.4');
is_numeric('1e7');
?>

With that said, is_numeric() does eliminate values that could compromise a database. The other invalid values can be removed by checking them against the database. If an ID isn't found, it's invalid.

Utilizing ctype_digit() Instead

Although is_numeric() will help protect our queries, there are many potential invalid IDs that could be eliminated by using the ctype_digit() function instead. This particular function only allows whole numbers—no decimals, no scientific notations, etc. So there's a better chance we'll have a valid value. To validate our ID, our code might look like the following:

<?php
if(ctype_digit($product_id)) {
    //it's a number, process query
} else {
    //not a number, display error
}
?>

Of course, there's still the chance of having invalid IDs. For example, zero (0) is number and probably won't be in the database. If the database only has 237 rows, 238 will be invalid. As before, these invalid IDs can be eliminated with a simple test against the database.

Conclusion

There are many ways to check if we have a number. No matter which one we choose, we'll still need to eliminate invalid IDs before running the main query. The important thing is to prevent the IDs from potentially damaging our databases.

0 Comments

There are currently no comments.

Leave a Comment