$_GET comes from the query string of any request, $_POST from a POST body in either form encoding. Both are already URL-decoded, so never urldecode() them. Here a cookie, a body and a query string all carry a field named id:
<?php
header('Content-Type: text/plain; charset=utf-8');
$all = ['GET' => $_GET, 'POST' => $_POST, 'COOKIE' => $_COOKIE, 'REQUEST' => $_REQUEST];
foreach ($all as $name => $values) {
printf("%-8s %s\n", $name, json_encode($values));
}Output
$ curl -sb id=cookie -d 'id=post&a.b=1&items[]=x&q[min]=3' "$U/dump.php?id=get&first+name=Ann"
GET {"id":"get","first_name":"Ann"}
POST {"id":"post","a_b":"1","items":["x"],"q":{"min":"3"}}
COOKIE {"id":"cookie"}
REQUEST {"id":"post","first_name":"Ann","a_b":"1","items":["x"],"q":{"min":"3"}}Dots and spaces became underscores, brackets built arrays (so any field can arrive as an array), and every value is a string. Past max_input_vars (1000) PHP warns and drops fields. $_REQUEST merges by request_order: Ubuntu 225 's "GP" lets POST beat GET and omits cookies, but an empty setting falls back to variables_order, where a stale cookie can override a field. Code reading $_REQUEST['delete'] also obeys a plain link. Name the array you mean: $_GET or $_POST.