For many PHP devs, their first experience with HTTP request parameters comes in the form
of the $_GET
and $_POST
superglobals. These globally accessible arrays are an easily
digestable abstraction of the HTTP spec. Indeed, for basic applications operating only in
the context of common browser user-agents, these eminently accessible parameter collections
work well.
But there are some significant problems with $_GET
and $_POST
under the surface:
-
Superglobal use violates basic OOP principles. The name superglobal in itself is a big red flag. We aren't just talking about
global
variables, these bad boys are SUPERglobal
variables. And though one of PHP's major strengths is first-class HTTP access, we should still avoid littering OO code with globals (and superglobals). Effective OO code should never directly access the$_GET
and$_POST
superglobals. -
The names
$_GET
and$_POST
are actually quite misleading as their functionality relates to the HTTP specification. While it's not the job of PHP to teach developers the nuances of HTTP, it should at least endeavor to avoid misrepresenting how HTTP requests work.
According to section 3.2.2 of the HTTP specification,
a valid URL may contain a query string regardless of the HTTP method verb used to access
it. This means that query parameters are part of the full request URL and are completely
unrelated to the HTTP GET method. As a result, PHP's $_GET
superglobal can be populated
for POST, PUT, DELETE or any other HTTP request method. A much more accurate name for an
array of parsed query parameters, then, might be something like $_QUERY
or $_QUERY_PARAMETERS
.
$_GET
has no correlation to the HTTP GET method, and naming it as if it does is patently
misleading.
$_POST
wasn't so bad in 1998 when the web was mostly thought of in terms of browser user-agents
that submitted forms via GET or POST. But PHP's $_POST
becomes a component of a larger
leaky abstraction in a world where RESTful APIs deal in HTTP methods like PUT and OPTIONS.
To understand why this is so, we need to understand where $_POST
data comes from.
The HTTP specification describes the entity-body as follows (rfc2616-sec7.2):
Request and Response messages MAY transfer an entity if not otherwise restricted by the request method or response status code. An entity consists of entity-header fields and an entity-body, although some responses will only include the entity-headers.
When a user-agent (browser) submits a form via POST, the browser encodes the form values and packages them in the standard key-value format:
formVar1=myValue&formVar2=myOtherValue
This string of parameters is sent in the entity-body portion of the HTTP message. As a
convenience, PHP parses this entity-body for you when POST forms are submitted and makes
the submitted values easily accessible in the $_POST
superglobal.
The problem here is that POST isn't the only HTTP method for which an entity-body is
appropriate. PUT requests require an entity-body and the HTTP OPTIONS method also optionally
allows entity-body data. $_POST
is therefore an incomplete representation of the larger
concept of entity-body parameters. It's only useful as a convenience wrapper for a very
specific operation.
Because the same method could be used to parse PUT parameters (but isn't by PHP), $_POST
would be much more appropriately named something like $_ENTITY_BODY_PARAMETERS
. This would
apparently be too confusing (or too long) for people to understand. Unfortunately, the result
is a generation of PHP developers who don't understand how HTTP works because PHP tells
them everything is GET and POST data.
Is there a patch to exclude / de-activate the superglobals for PHP, or is unset still the preferred method?