is_numeric or a numeric preg_match? - php

I read on a forum that you can't completely trust is_numeric(). It lets through "0xFF" for example which is an allowed hexadecimal...
So my question is can you trick is_numeric? Will I need to use a regex to do it correctly?

Here is what is_numeric() considers to be a numeric string:
Numeric strings consist of optional sign, any number of digits, optional decimal part and optional exponential part. Thus +0123.45e6 is a valid numeric value. Hexadecimal notation (0xFF) is allowed too but only without sign, decimal and exponential part.
If you only want to check if a string consists of decimal digits 0-9, you could use ctype_digit().

One can also check using ctype_digit() to check if its a true number.

Regex would obviously be your better option, however it does come with an overhead. So it really depends on your situation and what you want to do.

Is it for validating user input? Then the overhead of using a regexp or asserting it doesn't contain an "x" and is_numeric() wouldn't be too much overhead.

If you just want to check that something is an integer, try this:
function isInteger($value){
return (is_numeric($value) ? intval($value) == $value : false);
}
If you want to check for floats too then this won't work obviously :)

Related

PHP is_numeric or preg_match 0-9 validation

This isn't a big issue for me (as far as I'm aware), it's more of something that's interested me. But what is the main difference, if any, of using is_numeric over preg_match (or vice versa) to validate user input values.
Example One:
<?php
$id = $_GET['id'];
if (!preg_match('/^[0-9]*$/', $id)) {
// Error
} else {
// Continue
}
?>
Example Two:
<?php
$id = $_GET['id'];
if (!is_numeric($id)) {
// Error
} else {
// Continue
}
?>
I assume both do exactly the same but is there any specific differences which could cause problems later somehow? Is there a "best way" or something I'm not seeing which makes them different.
is_numeric() tests whether a value is a number. It doesn't necessarily have to be an integer though - it could a decimal number or a number in scientific notation.
The preg_match() example you've given only checks that a value contains the digits zero to nine; any number of them, and in any sequence.
Note that the regular expression you've given also isn't a perfect integer checker, the way you've written it. It doesn't allow for negatives; it does allow for a zero-length string (ie with no digits at all, which presumably shouldn't be valid?), and it allows the number to have any number of leading zeros, which again may not be the intended.
[EDIT]
As per your comment, a better regular expression might look like this:
/^[1-9][0-9]*$/
This forces the first digit to only be between 1 and 9, so you can't have leading zeros. It also forces it to be at least one digit long, so solves the zero-length string issue.
You're not worried about negatives, so that's not an issue.
You might want to restrict the number of digits, because as things stand, it will allow strings that are too big to be stored as integers. To restrict this, you would change the star into a length restriction like so:
/^[1-9][0-9]{0,15}$/
This would allow the string to be between 1 and 16 digits long (ie the first digit plus 0-15 further digits). Feel free to adjust the numbers in the curly braces to suit your own needs. If you want a fixed length string, then you only need to specify one number in the braces.
According to http://www.php.net/manual/en/function.is-numeric.php, is_numeric alows something like "+0123.45e6" or "0xFF". I think this not what you expect.
preg_match can be slow, and you can have something like 0000 or 0051.
I prefer using ctype_digit (works only with strings, it's ok with $_GET).
<?php
$id = $_GET['id'];
if (ctype_digit($id)) {
echo 'ok';
} else {
echo 'nok';
}
?>
is_numeric() allows any form of number. so 1, 3.14159265, 2.71828e10 are all "numeric", while your regex boils down to the equivalent of is_int()
is_numeric would accept "-0.5e+12" as a valid ID.
Not exactly the same.
From the PHP docs of is_numeric:
'42' is numeric
'1337' is numeric
'1e4' is numeric
'not numeric' is NOT numeric
'Array' is NOT numeric
'9.1' is numeric
With your regex you only check for 'basic' numeric values.
Also is_numeric() should be faster.
is_numeric checks whether it is any sort of number, while your regex checks whether it is an integer, possibly with leading 0s. For an id, stored as an integer, it is quite likely that we will want to not have leading 0s. Following Spudley's answer, we can do:
/^[1-9][0-9]*$/
However, as Spudley notes, the resulting string may be too large to be stored as a 32-bit or 64-bit integer value. The maximum value of an signed 32-bit integer is 2,147,483,647 (10 digits), and the maximum value of an signed 64-bit integer is 9,223,372,036,854,775,807 (19 digits). However, many 10 and 19 digit integers are larger than the maximum 32-bit and 64-bit integers respectively. A simple regex-only solution would be:
/^[1-9][0-9]{0-8}$/
or
/^[1-9][0-9]{0-17}$/
respectively, but these "solutions" unhappily restrict each to 9 and 19 digit integers; hardly a satisfying result. A better solution might be something like:
$expr = '/^[1-9][0-9]*$/';
if (preg_match($expr, $id) && filter_var($id, FILTER_VALIDATE_INT)) {
echo 'ok';
} else {
echo 'nok';
}
is_numeric checks more:
Finds whether the given variable is numeric. Numeric strings consist
of optional sign, any number of digits, optional decimal part and
optional exponential part. Thus +0123.45e6 is a valid numeric value.
Hexadecimal notation (0xFF) is allowed too but only without sign,
decimal and exponential part.
You can use this code for number validation:
if (!preg_match("/^[0-9]+$/i", $phone)) {
$errorMSG = 'Invalid Number!';
$error = 1;
}
If you're only checking if it's a number, is_numeric() is much much better here. It's more readable and a bit quicker than regex.
The issue with your regex here is that it won't allow decimal values, so essentially you've just written is_int() in regex. Regular expressions should only be used when there is a non-standard data format in your input; PHP has plenty of built in validation functions, even an email validator without regex.
PHP's is_numeric function allows for floats as well as integers. At the same time, the is_int function is too strict if you want to validate form data (strings only). Therefore, you had usually best use regular expressions for this.
Strictly speaking, integers are whole numbers positive and negative, and also including zero. Here is a regular expression for this:
/^0$|^[-]?[1-9][0-9]*$/
OR, if you want to allow leading zeros:
/^[-]?[0]|[1-9][0-9]$/
Note that this will allow for values such as -0000, which does not cause problems in PHP, however. (MySQL will also cast such values as 0.)
You may also want to confine the length of your integer for considerations of 32/64-bit PHP platform features and/or database compatibility. For instance, to limit the length of your integer to 9 digits (excluding the optional - sign), you could use:
/^0$|^[-]?[1-9][0-9]{0,8}$/
Meanwhile, all the values above will only restrict the values to integer,
so i use
/^[1-9][0-9\.]{0,15}$/
to allow float values too.
You can use filter_var() to check for integers in strings
<?php
$intnum = "1000022";
if (filter_var($intnum, FILTER_VALIDATE_INT) !== false){
echo $intnum.' is an int now';
}else{
echo "$intnum is not an int.";
}
// will output 1000022 is an int now

Turn zero filled numbers into whole numbers

I have a selection of nubmers which are prefixed with zeros to give them a set length.
0001,0230,1000,0007,0300
How could I make these whole number? So that the resulting numbers are
1,230,1000,7,300
I was using sprintf("%04d", $input); to generate the numbers, is there a reverse of this?
Thanks
If you feel safe that you have numbers and not another kind of string, you can just cast to integer:
(int) $num;
Demo: http://codepad.org/VQrA50fK
Just be aware that a non-integer (like a string with letters) will cast to 0.
Check out the intval function. Just pass them in and they'll be converted to ints. You can then append them to a sting to make them strings again.

Check if a variable is a natural number

I want to make a bid system on a website. That means users can post their bid (natural number). I want to make sure users don't try to post characters, decimal numbers, etc.
I don't want to use is_numeric function because hexadecimal notation is allowed.
I was thinking to use preg_match for this. But in php.net the documentation for this function is little and I have no idea how to use preg_match.
So how should I check if a variable is a natural number with preg_match?
If you don't require decimal points: ctype_digit or filter_var($var, FILTER_VALIDATE_INT).
If you do: filter_var($var, FILTER_VALIDATE_FLOAT).
ctype_digit does what you want:
Checks if all of the characters in the provided string, text, are numerical.
(Before PHP 5.1.0, this function returned TRUE when text was an empty string.)
Either preg_match('/^[0-9]+$/', $var); or ctype_digit
I would generally caution against using regex for parsing numerics, as there are generally better solutions than regex for this, but since you're asking, I'll try to give you some assistance with it:
preg_match uses regular expressions (regex) for it's matching.
You can find out more about regex syntax at sites like http://www.regular-expressions.info/
If you want to match a digit in regex, you can either use [0-9] or \d.
If you want to match one or more of anything, you would use a plus sign.
Finally, regex strings need to be enclosed in a pair of characters. The character chosen is usually a slash (/) character, as some languages specifically require this character, but PHP also allows other characters to be used; tilde (~) is quite common.
So your regex string to match any number of digits would be "/\d+/". This can then be put into a preg_match call like so:
$isnumeric = preg_match("/\d+/",$input_string);
If you have more specific requirements, you can limit the number of characters allowed by replacing the plus sign with {max} or {min,max} where 'min' and 'max' are the number of times the preceding match is allowed. So to allow a number between two and six digits long, you would use this:
$isnumeric = preg_match("/\d{2,6}/",$input_string);
If you need to allow a decimal point, you need to know that the dot character is a special character in regex (it means 'match any character at all'), so you need to escape it with a back-slash.
Therefore, a regex to match a currency amount with two decimal places, and at least one digit before the point would be like this:
$isnumeric = preg_match("/\d+\.\d\d/",$input_string);
Finally, note that regex will return true in all the above if the string simply contains the matched value. To ensure it doesn't contain anything else, you would need to 'anchor' it to the front and end of the string, using the anchor characters: ^ for the start of the string, and $ for the end.
So for the previous example, if you want it to only contain a decimal number, and nothing else, you would need this:
$isnumeric = preg_match("/^\d+\.\d\d$/",$input_string);
Regex is a complex subject, but I hope that gives you a start.
I know this is very old but I wanted to share the next solution in case someone else comes up with this problem.
I'm assuming that by natural number you meant positive integer (which excludes the number 0).
function is_positive_integer( $value ) {
// Check if is integer and greater than zero
if( is_int( $value ) && $value > 0 ) {
return true;
}
// Is not a positive integer
else {
return false;
}
}
This kind of depends on your definition of natural numbers - according to different theories, the number zero (0) does or does not count as a natural number.
To answer your question on how to solve this with preg_match:
If you want to include zero, using preg_match is pretty easy preg_match('^[0-9]+$', $input).
Usage:
if (preg_match('^[0-9]+$', $input))
// $input represents a non-negative numeric value
else
// $input does not represent a non-negative numeric value
If you don't want to include the zero, use preg_match('^[1-9][0-9]*$', $input):
if (preg_match('^[1-9][0-9]*$', $input))
// $input represents a positive numeric value
else
// $input does not represent a positive numeric value
That said - for your particular problem, using ctype_digit is a faster solution, as others already pointed out (you'd have to do a second check if you don't want to allow the number zero).
in_array(str_replace(str_split('0123456789'), '', $s), array(',','.',''));
simple function:
function isnature($x){
$y = ceil($x)-floor($x);
return $y == 0 ? true : false;
}
From a mathematical point of view, a natural number is a positive integer, including zero, so you could check it like this:
is_int($bid) && $bid >= 0
Simplest and faster
if( is_numeric( $key ) && intval( $key ) == $key )
{
//key == number
}

How to check if variable is Alphabetic or Numeric in PHP?

How to check if variable is Alphabetic or Numeric in PHP?
Depending on how you define numeric, you'll use one of the following functions :
is_numeric
ctype_digit
With the first one, numeric is defined as (quoting) :
Numeric strings consist of optional
sign, any number of digits, optional
decimal part and optional exponential
part.
While, with the second one, you will (quoting) :
Checks if all of the characters in the
provided string, text, are numerical
And, for alphabetic, you'll be interested by :
ctype_alpha
Quoting :
Checks if all of the characters in the
provided string, text, are alphabetic.
In the standard C locale letters are
just [A-Za-z]
And, as pointed out by #Long Ears in his comment, if you want to check both in a single shot, you'll find the ctype_alnum() function (quoting) :
Checks if all of the characters in the
provided string, text, are
alphanumeric.
In any case, you might want to take a look at the full list of Ctype functions.
Use the is_numeric function:
is_numeric("42"); // true
is_numeric(1337); // true
is_numeric("1e4"); // true
is_numeric("not numeric"); // false
is_numeric(Array()); // false
is_numeric(9.1); // true
You can use is_numeric() or ctype_alpha() functions
you quick test the input val by if numeric or alpha`enter code here`
using this php function
if(ctype_alnum($eafrik)){
echo "is alphatnumeric";
}else{
echo "is not alphanumeric"
}

What is wrong with this simple line of PHP?

is_int($_GET['pid']) ? define(PRODUCT, $_GET['pid']) : die('Invalid Product Id');
even if the value of pid is an integer I still get the Invalid product id message. Why?
Like the manual says: To test if a variable is a number or a numeric string (such as form input, which is always a string), you must use is_numeric().
Edit: Though it's implied by my answer here, I'll be more specific: $_GET's contents is strings, so an is_int call will always return false. If what you really want to verify here is that the contents of a particular string represents a integer number, you can use a call to is_numeric.
values in the $_GET array are usually type string, but sometimes type array as well.
use ctype_digit() to check if a string is entirely digit characters. optionally, trim() the string first. only use is_numeric() if you want to accept strings in a wide range of formats that are sometimes interpreted numerically, such as decimals, scientific notation, hex strings etc...
$_GET[] always returns strings, so is_int() always evaluates to false. Try is_numeric() instead.
Anything in $_GET is string, and is_int("2") returns false.

Categories