is_int, is_numeric, is_float, and HTML form validation - php

A select field on my HTML form may yield 1 to 5 (integers). Using is_int rejects it every time, because the $_POST['rating'] is viewed as a string.
After consulting the PHP Manual, it seems is_numeric() && !is_float() is the proper way to validate for an integer in this case.
But I want to be certain, so please confirm or fire away at my logic.

I would probably use something like this:
$value = filter_var(
$_POST['rating'],
FILTER_VALIDATE_INT,
array('options' => array('min_range' => 1, 'max_range' => 5)));
filter_var() will return either boolean false if the value is non-integer or out-of-range, or the valid value itself (as an integer.)

I would use is_numeric(), because user input always comes in as a string (as far as I know).
Another way to guarantee something is an integer is to cast it...
$id = (int) $id;

You could use the following regular expression:
preg_match('/^[0-9]{1,}$/', $value);
I does validate digits with leading zeros though...

if you want to know if $_POST['rating'] is an int before you even try to cast do use is_numeric() && !is_float() as you have. This will tell you if the string is an int or not. If you just cast to an int and there is a non numeric all the numbers before the first letter in the string is turned into an int.
x = 457h
print (int)x
outputs 457
x = h56
print (int)x
outputs 0

is_int requires the input content is a integer.
is_numeric requires the input content is a integer or a string including just 0-9.
but I am wondering the result if I put a number that is bigger than PHP_INT_MAX as the parameter into the above 2 functions.

You can always cast it as an int.
$rating = (int)$_POST['rating'];
This will remove the need to validate it (even though you should always validate form data).
It may reduce your steps is what I'm getting at.

If you're testing for digits only (what an integer usually is ;)), I tend to use ctype_digit instead of is_int. That way, you won't lose data through casting, and you can just use a string:
<?php
$_POST['foo'] = '42';
echo ctype_digit( (string) $_POST['foo'] ) ? 'yep' : 'nope';
That'll output "yep".

Related

Why does this happen in php when we multiple string by number it always gives zero(0)?

Suppose we have a string $str = "a"; and number $num = 2;
$str = 'a';
$num = 2;
echo $str*$num;
Output:
0
When performing arithmetic operations on a string operand, PHP will try to convert the string to a number.
It does this by looking for digits at the beginning of the string and will try to convert them into a value. If there are no digits, the value will be zero.
(There's an edge case for strings containing e or E (scientific notation), but that's not relevant here.)
Good Question.
Same i did ask to my teacher when i was in collage,
The answer is.
String * int= infinity; //According to scientific calculator answer is infinity.
but we need to continue our so program it provide 0.
it is made by code by default answer.
Simply said the string will be converted to an integer with a value of 0. This will include most of the cases when only alphabetic values are used. If you try to add a integer value at the beginning of the string it would in theory become a integer of that value.
I would recommend to read Why PHP Strings Equal Zero or Comparison Operators
Maybe you are looking for str_repeat, instead doing looping for that, its a default value that php serve to you, or you need to cast A into integer . When you try to do calculation for data that is not in Integer/float data type. Usually PHP auto-typecast the variables. In some cases it wont. Then we have to type cast it manually

convert a '$_GET' hex value (string form) to hex int -- how?

I suspect this might be a duplicate but lord if I can find it.
I need to convert a 'mostly' hex value passed in the _GET[] array from string to an actual hex integer. I say 'mostly' because the hex number passed in is not prepended with the "0x"
The most promising thing I tried and then raised the white flag on this problem was this -- 'azk' is the name of the GET[] parameter passed in:
$timeStamp = filter_input(INPUT_GET, 'azk', FILTER_SANITIZE_STRING);
//FAILS FOR HEX --> $test = (int)$timeStamp;
//FAILS FOR HEX --> $test = 0 + $timeStamp;
$retval = sscanf($timeStamp, '%x', $test);
var_dump(gettype($test));
var_dump($test);
Here's what happens: the user passes in an 'azk' value of 531cb6d6, which is in fact a hex value but not prepended with the '0x'.
Despite my instructions to sscanf() above -- note that I specifically instruct sscanf() to convert the value of 'timeStamp' into a hex value by way of the '%x' flag --
-- the $test value is shown, via the var_dump's above, as this:
string(7) "integer" int(1394390742)
The '1394390742' is not hex. I'm not seeing why, I specifically instruct sscanf to convert to %x hex value, but this '1394390742' is the base-10 (decimal) version of the base-16 (hexadecimal) value that got passed in, the 531cb6d6 value. In other words, using "%x" is converting hex to decimal. Not sure if that is a bug, a setting in the web server ini files somewhere, or a lack of my understanding of "%x".
The sscanf() is not all I've tried, this is not exhaustive but I tried things like this, to me the most obvious choice:
// BOTH OF THESE FAIL TO PASS HEX CHARS, BOTH RETURN THIS: 53166
$timeStamp = filter_input(INPUT_GET, 'azk', FILTER_SANITIZE_NUMBER_INT,
FILTER_FLAG_ALLOW_HEX);
$timeStamp = filter_input(INPUT_GET, 'azk', FILTER_VALIDATE_INT,
FILTER_FLAG_ALLOW_HEX);
I've looked at a bunch of SO posts, I can't believe this isn't covered, but I can't find it. If someone knows how to pull this off -- convert a hex value passed by the _GET as a string, then convert to a hex value -- I would be in your debt.
As var_dump shows, the variable $test contains an integer.
PHP is converting the integer back to a decimal string just so it can show it, but the integer itself is not intrinsically decimal, nor hex. Those are just two possible representations of the same value.
If you want to output the value back as an hex string, you can use one of these:
echo dechex($test);
printf("%x", $test);
Edit: I saw your comments, you don't need to cast as int:
1) hexdec takes the string and returns an integer
2) ...do the math using integers...
3) dechex takes the result as integer an returns a string
You can use the hexdec() function:
$timeStamp = hexdec('531cb6d6'); // 1394390742
If you want to sanitize the string before using it then you can create your own filter using a callback:
$hexTimestamp = filter_input(INPUT_GET, 'azk', FILTER_CALLBACK, array(
'options' => function($str) {
return ctype_xdigit($str) ? $str : 0;
}
));
$timeStamp = hexdec('531cb6d6');
If you not going to use the HEX value then you could also convert it to an integer as part of the sanitizing:
$timestamp = filter_input(INPUT_GET, 'azk', FILTER_CALLBACK, array(
'options' => function($str) {
return ctype_xdigit($str) ? hexdec($str) : false;
}
));
Edit:
Okay, I am getting confused, I think. You have a HEX input and you want to turn it into a "HEX number". I am not sure I understand what you mean.
If you want the input HEX value to become a "real" PHP HEX value, like 0x531cb6d6, then you are mistaken about how PHP works. When PHP sees a HEX constant, like 0x531cb6d6, then it immediately converts it to an integer. PHP does not use HEX numbers; HEX notation is just a way of representing a number, and it not actually a type of number distinct from integers.
If you want the input HEX value, "531cb6d6", to look like a HEX value with the 0x prefix then you can just add it: '0x'.$timeStamp.
Not sure if I answered your question.

PHP equivalent of JavaScript's parseInt function? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Check if a variable is a natural number
Just came across where I need to sanitize an input and remove all non-digit characters with PHP. Thought of making a function myself, but just first wanted to check up on the possible built-in functions, so I won't have to spend extra time reinventing the wheel.
There isn't a direct equivalent to pareseInt() in PHP because PHP doesn't have a NaN data type. parseInt() will produce NaN if the value can't be parsed.
In addition, parseInt() has the radix parameter, which none of the PHP options give you.
But that said, if all you want to do is turn a string into an integer, then there are several options:
$int = (int)$string;
$int = intval($string);
$int = settype($string,'integer');
Those three will all work in much the same way. There may be some edge cases where intval() differs from the other two, but in general, they will turn a string into an int. In the absence of NaN, they all output 0 (zero) if the string is non numeric and can't be parsed. But this should be sufficient for most DB sanitation purposes.
If you really want a the NaN on error, the closest you'll get is null. You can get this using filter_var():
$value = filter_var(FALSE, FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE);
If you just want to check that the string is numeric, the is_numeric() function can do that:
$bool = is_numeric($string);
However, it returns true for decimals and also for scientific notation, so may not be perfect for most situations. A better option is ctype_digit() which returns true if the string is made up only of digits:
$bool = ctype_digit($string);
If non e of this suits, there is always the regex option, using preg_match() or preg_replace(), but these are definitely overkill for this kind of scenario.
You can use regular expression as below
$int = (int) preg_replace('/\D/', '', $strNonNumeric);
OR
$int = (int) preg_replace('/[^0-9]/', '', $strNonNumeric);
You can use:
$string = "90"; //string
$myInt = (int) $string; //parse to int
I would recommend using FILTER_VALIDATE_INT Filter.
about Filters on php.net
You can also use sscanf (just like you do in C)
<?php
$str = "10";
sscanf($str, "%d", $intVal);
$intVal *= 10;
echo $intVal;
?>
Output:
100

PHP Bug with Conditional Operator?

$i=0;
$j='00:15';
if ($i==$j)
echo "equal";
else
echo "not equal";
displays equal?
00:15 is cast into an integer first and then compared with $i. Since intval() (which does the casting) stops at the first non-numeric character, 00:15 is cast into zero, which is equal to zero. No bug here, this is how the == operator works.
If you want to avoid casting, use === instead.
Using the == the types will be converted before they are compared. In this case, both will be converted to an integer, and when you convert a non-numeric string to an integer, it will probably result in 0.
If you use the === operator instead, you will get the result that you expect.
string and int compares as int's, So $j converts to 0 here because starts with 00
Not bizarre at all - when comparing string with integer, the first one is being cast to integer then compared. Use === for type checking and you'll see the real result
Turns out the === is problematic
for example 10===10 will be false if one is integer and one is string even though they are identical as can happen from forms posting.
the solution i used was:
if ("$i"=="$j")
this way it just checks if they're identical regardless of type

is_numeric() vs. is_float() vs. is_int()

My understanding is...
if is_numeric($input) === true
then either
is_float($input) === true OR
is_int($input) === true OR
$input === 0 OR
$input is a numeric string (meaning it'd satisfy one of the first 3 if it weren't wrapped in quotes).
Is that accurate? Are there other differences?
See PHP's documentation on is_numeric. It talks about everything that is allowed, and it's more than is_float and is_int.
It's also important to note that is_int only works on things that are type integer, meaning string representations are not allowed. This is a common problem when verifying that form input is an integer. You should use filter_var or something from the filter family with the filter FILTER_VALIDATE_INT. For floats, use FILTER_VALIDATE_FLOAT.
Also, if the reason you are trying to check for an integer is to validate a parameter as being an int, then in PHP 7 you can do this:
function foo(int $i) {
// $i is guaranteed to be an int (is_int) will be true
}
PHP 7 has two different modes for converting to int; this answer explains it a bit more.
Note that this is probably not what you want if you are validating the contents of a form element. Use the filter_var solution for that.
See the docs. A numeric value can be:
An integer
A float
Exponential
A positive Hexadecimal
A string containing most of these

Categories