A recent thread split on the PHP Internals list has been about the use of the $_REQUEST variable. I have seen more than one person make the following logic mistake:

  1. I may get data via GET

  2. I may get data via POST

  3. Ah, I should use $_REQUEST as it will catch both.


There is a problem with that logic. Cookies! Cookies are also put ino $_REQUEST. In fact, they are put into $_REQUEST last. So, any data that was sent via GET or POST is overwritten by cookies of the same name.

When does this cause a problem? Well, let's say you have a script that has a form that asks for a user name. You call the field username. So, you are looking for that data in $_REQUEST. Unknown to you, another member of your team makes a cookie named username on a totally unrelated application. His cookie needs to be accessible from several parts of the site, so he assigned the cookie to the path /. So, now, when a user submits your form, the data comes in looking like this:

$_GET["username"] = "user input";
$_COOKIE["username"] = "Tom";
$_REQUEST["username"] = "Tom";


So, now you have bad data for the username you wanted. This becomes even more menacing when you start thinking about security issues like XSS or CRSF. As Stefan Esser, a strong PHP Security advocate, wrote in another reply to the thread:
Just imagine my example...

switch ($_REQUEST['action'])
{
case 'logout':
logout();
break;
...
}

When someone injects you a cookie like +++action=logout through an
XSS or through a feature like foobar.co.kr can set cookies for *.co.kr
(in FF atleast).
Then you CANNOT use the application anymore. This is a DOS. You cannot
defeat this problem except detecting and telling the user to delete his
cookies manually...

Yikes! So, now you have all kinds of problems with using $_REQUEST.

So, what is the best way to handle both GET and POST data? Well, here are a couple options.

Merge GET and POST data

You could use array_merge() to merge the $_GET and $_POST variables into one. I would use a new variable for this data. You can overwrite super globals. Some think it is a bad idea. I can't argue that it could cause confusion if you did this in an environment where several parts of the application are going to be using user input. If you do want to do this you could do the following.

$user_input = array_merge($_GET, $_POST);
// or overwrite $_REQUEST - not recommended
$_REQUEST = array_merge($_GET, $_POST);


Use GET OR POST, not both

I personally like to only use either $_GET or $_POST. I have very rarely seen a case where using both made sense.  I normally favor $_POST if it is set.

if(!empty($_POST)){
$user_input = $_POST;
} elseif {
$user_input = $_GET;
}


Now we have a save array that can be used and we know that the data only came from one place.