5

I'm not sure how to handle this one, and I've tried what to me are the most obvious solutions, but so far none have proved entirely satisfactory. I must be overlooking something very simple.

I have a form with an input of type text:

<input type="text" name="album_id">

I want to validate the input so the users only enters unsigned integer...

$required = array(); // required or invalid input

$tmp = trim($_POST['album_id']);

if (!is_int((int)$tmp)) {
   $required['album'] = 'The album id must contain a positive numeric value only.';
}

So far I've use !is_numeric($tmp) but a user can enter 9.2 or '1e4' and it will validate... so that one doesn't work.

I've also tried !is_int((int)$tmp) but for some reason, that one doesn't work (maybe it should but i'm doing it wrong...). I tried ctype_digit with no success. I'm probably overlooking something but not sure what.

How can I validate an unsigned number in php? No floats, negative numbers, etc... only a simple unsigned number (1 to n).

Benjamin Loison
  • 3,782
  • 4
  • 16
  • 33
Marco
  • 213
  • 3
  • 5

4 Answers4

8

If you want to check if some variable only contains digits (which seems to be what you want, here), you'll probably have to go with ctype_digit().


Not sure what you tried, but something like this should work :

$tmp = trim($_POST['album_id']);
if (ctype_digit($tmp)) {
    // $tmp only contains digits
}
Pascal MARTIN
  • 395,085
  • 80
  • 655
  • 663
  • indeed... i've put the NOT sign like this !ctype_digit($tmp) and it seems to work ok! i think the documentation trhew me off when it show that $integer = 42; // false I've forgot that the input is a string by default not an integer.... thanks – Marco Apr 03 '11 at 10:40
4

The filter_var() function is the right tool for the job here.

Here's a filter that will return non-false only for unsigned integers or unsigned integer strings:

$filteredVal = filter_var($inputVal, 
                          FILTER_VALIDATE_INT, 
                          array('options' => array('min_range' => 0)));

Here's the documentation on filters.

Example:

<?php

$testInput = array(
            "zero string" => "0",
            "zero" => 0,
            "int" => 111,
            "string decimal" => "222",
            "empty string" => "",
            "false" => false,
            "negative int" => -333,
            "negative string decimal" => "-444",
            "string octal" => "0555",
            "string hex" => "0x666", 
            "float" => 0.777,
            "string float" => "0.888",
            "string" => "nine"
         ); 

foreach ($testInput as $case => $inputVal)
{
    $filteredVal = filter_var($inputVal, 
                              FILTER_VALIDATE_INT, 
                              array('options' => array('min_range' => 0)));

    if (false === $filteredVal)
    {
        print "$case (". var_export($inputVal, true) . ") fails\n";
    } 
    else
    { 
        print "$case (". var_export($filteredVal, true) . ") passes\n";
    }
}

Output:

zero string (0) passes
zero (0) passes
int (111) passes
string decimal (222) passes
empty string ('') fails
false (false) fails
negative int (-333) fails
negative string decimal ('-444') fails
string octal ('0555') fails
string hex ('0x666') fails
float (0.777) fails
string float ('0.888') fails
string ('nine') fails
John Carter
  • 53,924
  • 26
  • 111
  • 144
  • Beware 32 bit limitations: 2147483647 passes the check "integer >0". 2147483648 fails. Adding quotes does not seem to be any helpful. – wtf8_decode Mar 25 '15 at 20:17
1

You could use preg_match():

if(preg_match('/^[\\d+]$/', $tmp) == 0)
    $required['album'] = 'The album id must ...';

Note that this won't do a positive range check (e.g. getting above the max valid value of an integer).

Edit: Use Pascal MARTIN's solution unless you'd like to do more complex checks (e.g. requiring other special characters), as I'd guess it offers better performance for this use.

Mario
  • 35,726
  • 5
  • 62
  • 78
1
if (preg_match('!^[1-9][0-9]*$!',$tmp)) {
Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
  • "0" and something like "0123" are still valid integer values. I wouldn't assume anyone would expect those numbers to be read as octal numbers. – Mario Apr 03 '11 at 10:33