Forum Moderators: coopster

Message Too Old, No Replies

Preg match to kill if anything except numbers in the query string

         

jake66

3:55 am on Mar 12, 2010 (gmt 0)

10+ Year Member



I am trying to throw an error if the query string has ANYTHING but numbers present.

I've tried a range of different code, but this is my latest and it doesn't seem to work:
if (!preg_match('/[[:^digit:]]/', $_GET['number'])){
echo'You must not enter anything but a digit.';
}


Basically, if someone enters a - or letter (for example), the form stops processing. Any tips on what I'm doing wrong?

Readie

7:58 am on Mar 12, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



if(!preg_match('/[^0-9]+/', $someVaraiable)) {
// Do processing
} else {
// Error
}

coopster

2:09 pm on Mar 12, 2010 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



You had it almost right there, jake66. Except you are doubling your negation. Once in the regular expression and then once again in the reversal of logic. Remove the reversal of logic (the exclamation point) and your test should work as you expect.
if (preg_match('/[[:^digit:]]/', $_GET['number'])) {

jatar_k

2:15 pm on Mar 12, 2010 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



if (!ctype_digit($_GET['number'])) echo'You must not enter anything but a digit.';

there are a lot of ways to skin this one ;)

is_int would probably work too

coopster

2:58 pm on Mar 12, 2010 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



careful with is_int ... is_int won't consider a string value as integer even if the string represents an integer value. It will return different results than you expect.

jatar_k

3:39 pm on Mar 12, 2010 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



sorry I should have mentioned that, thanks coop

is_int(23) true
is_int("23") false
is_int(23.5) false
is_int(true) false

Readie

3:44 pm on Mar 12, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I believe is_numeric covers floats - Though I've never tried using it on quoted numbers

rocknbil

8:11 pm on Mar 12, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



<oops misread . . . again>

as one who always reverts to regexps, often when I shouldn't, regexps operate on strings. One of the numeric PHP functions should be more appropriate . . .

if (! is_numeric($var)) { // error }

If you want to go the regexp route, [0-9] is identical to \d, but you need the dot for decimal numbers. Don't forget the beginning/ending string delimiters, ^ outside a class means "beginning of string," $ is end.

^ inside a character class means anything NOT these characters.

if (! preg_match('/^[\d\.]+$/',$var)) { // error }

0r

if (! preg_match('/^[0-9\.]+$/',$var)) { // error }

or - and this one's trickier, using the not in the class - "if it matches on anything NOT a digit or dot"

if (preg_match('/^[^\d\.]+$/',$var)) { // error }

WesleyC

9:03 pm on Mar 12, 2010 (gmt 0)

10+ Year Member



One trick I like to use is PHP's intval()/floatval() functions. Cast the input into an integer or float with these functions, then compare its value to an expected range (for instance, database-generated numeric IDs generally start with 1, so you should probably throw out the input if the value is less than 1). If the input string was not numeric, the functions will return false.

$var = intval( $_POST['input'] );
if ( $var > 1 )
{
// valid number, do processing
}
else
{
// invalid number, display error
}

jake66

5:25 am on Mar 14, 2010 (gmt 0)

10+ Year Member



Wow, plethora of great examples here. Thanks, guys!

Any chance there's something I'm doing wrong here? Trying to condense some code fragments..

This works:

if(isset($_GET['number'])){
if(!preg_match('/[^0-9]+/', $_GET['number'])) {
$stripped = (int)$_GET['number'];
}else{
echo'You must not enter anything but a digit.';
}
}


This does not:

if(isset($_GET['number'])&& (!preg_match('/[^0-9]+/', $_GET['number']))) {
$stripped = (int)$_GET['number'];
}else{
echo'You must not enter anything but a digit.';
}
}

Readie

8:02 am on Mar 14, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'm not sure on this as I've never done it, but I think it's because you don't have a space before the &&.

Try this:

if(isset($_GET['number']) && !preg_match('/[^0-9]+/', $_GET['number'])) {

rocknbil

9:07 pm on Mar 14, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You've changed gears and are doing the opposite now. :-) From your original post:

I am trying to throw an error if the query string has ANYTHING but numbers present.


You're doing the opposite now, validating with only numbers in the regexp and throwing an error if it doesn't match. Most of the solutions posted are the other way around:

if ([what I don't want is found]) { error; }
else { OK }

The difference is they require slightly different regexps (but still, you should be going with php numeric functions . . . )

You have also raised the point (pun intended) there may be floats/decimal #'s, you need a dot in your regexp.

Your regexp also needs the beginning/ending string delimiters, otherwise it will still pass with abc123def (see my previous post.)

Since you're going with regexps,

if(isset($_GET['number']) and preg_match('/^[\d\.]+$/', $_GET['number'])) {
$stripped = int($_GET['number']);
}
else {
echo 'You must not enter anything but a digit.';
}

OR, because 0-9 and \d are equivalent,

if(isset($_GET['number']) and preg_match('/^[0-9\.]+$/', $_GET['number'])) {
$stripped = int($_GET['number']);
}
else {
echo 'You must not enter anything but a digit.';
}

I've never seen this,

(int)$_GET['number']

See example above, this one's new on me.

Readie

9:22 pm on Mar 14, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Does it make a difference which way round it's done? If anything, I would have thought looking for anything-not-numbers(and decimal points) and throwing an error on match would be better, because the preg_match doesn't need to check the entire string.

Matthew1980

9:27 pm on Mar 14, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hey there Rocknbil,


$stripped = (int)$_GET['number'];


From what I have understood doing similar in the past, this just forces the value held by the var to be a whole int. At least that's how I have always been told as it does. ;-p

Cheers,
MRb

rocknbil

10:06 pm on Mar 14, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Does it make a difference which way round it's done?


Only in that it needs different regexps . . . and that in trying to assist, the solutions on page 1 are trying to address it one way, here, the opposite.

The "stock" statement for validating input: accept what you want and throw everything else away. So just a preference, I'd do the positive match above.

Wait, no I wouldn't. I've be using PHP numeric functions. :-P

From what I have understood doing similar in the past, this just forces the value held by the var to be a whole int.


Isn't that what this does? int($var)

I guess they're equivalent? I have just never seen it in the wild.

Readie

8:28 am on Mar 15, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The "stock" statement for validating input: accept what you want and throw everything else away. So just a preference, I'd do the positive match above.

Wait, no I wouldn't. I've be using PHP numeric functions. :-P

Lol, OK, fair enough. With no output from the preg_match I guess it comes down to personal choice in the end.

jatar_k

12:55 pm on Mar 15, 2010 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



I used to use (int) in the old days quite a bit since there were some functions that didn't quite get the dynamic typing right, I don't remember what functions they were as it was 7 or 8 years ago. Another option is to multiply by 1, which I found more reliable in most cases.

[php.net...]
[php.net...]