$_GET or $_POST v's filter_input() functions

Hello All,

Read an interesting article on the phparch website, which suggests you should not use $_GET or $_POST again instead you should use functions built into PHP 5.2+ like filter_input() here:

http://www.phparch.com/2010/07/08/never-use-_get-again/

Now just have a couple of questions about this:

  1. What are people’s thoughts on this? Is this what we should be moving to?
  2. So if i’m reading this right would you swap the old way for the new way below for $_POST? This the right way to do it?

So for $_POST should I swap the old way for the new way like so:


//Old Way
$name = trim(mysql_real_escape_string(htmlentities(strip_tags($_POST['name'],ENT_QUOTES))));
$address = trim(mysql_real_escape_string(htmlentities(strip_tags($_POST['address'],ENT_QUOTES))));

//New Way
$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
$address = filter_input(INPUT_POST, 'address', FILTER_SANITIZE_STRING);

  1. With regards to $_GET I currently do things like typecast if it’s a number and use mysql_real_escape_string on characters.

So if I have a numbered URL like so i’d do:

webpage.php?num=37738292


//Old Way
$num = (int) $_GET['num'];
$query = "UPDATE tbl SET something = '1' WHERE num  = $num";

And if I have a string URL like so i’do:

webpage.php?num=dog


$num = mysql_real_escape_string($_GET['num']);
$query = "UPDATE tbl SET something = '1' WHERE num  = '$num'";

So therefore if I run the filter() function here I don’t see where it does the checking for either typecasting or using mysql_real_escape_string if i’m using a string for $_GET where’s the difference?


$num = filter_input(INPUT_GET, 'num', FILTER_SANITIZE_STRING);
$query = "UPDATE tbl SET something = '1' WHERE num  = $num";

Thanks

Chris

I don’t see the advantage of it.

I basically sanitize the way you do it as well.

If you have the presence of mind to write that hideously long line to sanitize/filter whatever, you should have the presence of mind to filter get/post variables.

I usually use filter_var to validate email addresses, that’s about it.

For a form, I simply have a recursive function that will sanitize all post variables if it’s going into a DB, one line of code vs having to call that for every variable - seems no brainer.

Using whatever built in function (if any) is available to do the filtering for you is best since it is the version least likely to have errors.

So using is_numeric() to test for numeric fields and is_alphabetic() to test for fields that can only contain letters is the best alternative for validating those field types. Casting to an int will only work if the value is a valid int in the first place and so an invalid input value would cause the script to crash.

No it doesn’t. Anything that isn’t a valid int in the first place will be cast to 0.

I’ve never used these functions but I don’t see any real advantages. They really look nice but I already find a few negative aspects:

  1. They usually take longer to type. For example, what could be shorter, faster and simpler than using (int) $var?
  2. I have to memorize all the constants for use with these functions or look up the documentation often.
  3. While some validators seem to help, what they do under the hood can be obscure since not every filter or flag is fully documented.

I think using simple php functions and constructs is in no way more difficult or problematic than the filter functions. I just use (int), (float), trim, substr, str_replace, etc. for sanitizing and preg_match is unmatched for validation with almost unlimited customization. At least it’s plain clear to me what my code is doing.

No it doesn’t. Anything that isn’t a valid int in the first place will be cast to 0.

Yeah, and this is quite different to JavaScript (which turns it into NaN) - 0 is still an integer. I find that rather irritating. PHP should turn something non-numeric into boolean false or maybe have its own NaN.

That is the equivalent of crashing since the entered value isn’t zero and shouln’t be treated as such. The code has crashed in that it has processed the entered value incorrectly. Converting all non-numeric values to 1 would make at least as much sense.

It’s not crashing because the value after sanitization is in the proper numeric format so there’s no reason for anything to crash. It also depends what what you use the value for - in most cases a numeric value from POST/GET is a database id, which is an autoincrement field and thus cannot be 0. Therefore casting to int in php is perfect for sanitizing: the value is in safe format to send to an sql query but you are sure no record will be found for that value, so it’s not equivalent to a crash but to “the item has not been found”. Therefore casting to int is very convenient in my opinion and I’m not fond of javascript NaN, which makes things more complicated. When I want to disallow non-numeric values being converted to 0 then I simply use proper validation, (int) is only for sanitizing. And converting non-numeric values to 1 would be the least logical behaviour because for most systems id=1 is a valid id while id=0 is never valid just like any string that has been entered instead of a poper number. Note that mysql also casts non-numeric strings to 0.

The impact on a developers poor, overworked finger joins, while obviously an issue we should always be aware of, seems silly. Why write your code in PHP when there are much terser languages available which may get the same job done with less typing. (I’m just poking fun here.)

Of course, (int) $var and using FILTER_SANITIZE_NUMBER_INT are two entirely different things and to get something comparable to the sanitizing filter in “normal” PHP would be much more work than simply casting to an int. If you’re going to make comparisons, at least compare apples to apples.

No you don’t. The constants follow a regular structure (e.g. types of input start with INPUT, validators start with FILTER_VALIDATE, they use names familiar to you elsewhere (GET, *_STRING, etc.) and besides, your editor/IDE is special enough to know about these things, right? Do you know all of the functions that you use in your code, and their parameters’ values/orders?

You are invited to file a bug report on the PHP system[1] reporting the lack of, or inadequate, documentation. For what it’s worth, there are no open documentation bugs referring to the filter docs. Pointing out specific problem areas (individual flags that you would like looked at) would be nice, if only to have specific targets to attack rather than “improve filter docs”. Without this sort of feedback, the documentation team has no idea of where folks are having issues/problems or when the docs are making life unnecessarily difficult for its users.

This is a very good point. There is a learning curve involved with using the filter extension and for those unfamiliar (or not intimately familiar!) with it, then it may well be easier and clearer to get the job done with tools they are more familiar with.

[1] http://bugs.php.net/report.php

i actually love how it handles sanitization. ive created a function that i use in my class to easily sanitize without having to type all that out.

function secure($field,$type)
{
switch($type)
{
case 'get':
$ouput = filter_input(INPUT_GET, $field, FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES);
break;

case 'post':
$output = filter_input(INPUT_POST, $field, FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES); 
break;

default:
break;
}

return $output;
}

so anytime i need to sanitize something i simply type for example:


$username = secure("username", "post");
//the first param is the field name usually put in $_POST['field'] 
//and the second param is the type i want to use.

At least know we know what we’re talking about (for me crashing means coming to an abrupt, abnormal halt) :slight_smile:

Off Topic:

Anyways, I’ve got some new things to study. PDO (it’s been on the list for a while already, and now filters. Why does a day have only 24 hours… :frowning: