The Scourge Of The PHP SuperGlobal: Why Form Variables Are So Hard To Kill

This is the first of a three-part series on handling PHP form postbacks. Today’s topic: The scourge of the PHP superglobal, and how hard they are to kill. Part 2: Quick-and-simple server side form validation via PHP. Part 3: The Holy Grail of PHP: Eliminating, for sure, the ability to resubmit a form.

Sent to me via email recently:

I’ve been looking at the three examples posted in June of 2009 on https://www.dougv.com/2009/06/retaining-values-in-a-form-following-php-postback-and-clearing-form-values-after-successful-php-form-processing/

None of these nice examples does exactly what I want, and I’m wondering which of them is most easily modified to accomplish what I do want, which is to

(a) display the clean form on some page.

(b) if the user provides entries that do not validate, to display the errors on the same page along with the form (retaining entries provided, awaiting corrections), or

(c) if the user provides entries that do validate, to send the user to a second page, where the (now validated) entries are available, but without re-displaying the form. (This would typically be a “Thank you” page.)

Any thoughts about what might be the best way to accomplish this?

Featured photo by sharonang via Pixabay, in the public domain.
Cleaning up after a PHP postback is a challenge, but it can be done. Featured photo by sharonang via Pixabay, in the public domain.

This is the Holy Grail of processing a server post-back form in PHP: Ensuring that once validated and processed, the user cannot resubmit the form.

There are lots of use cases where this makes sense: Taking a credit card payment comes immediately to mind, as does making a reservation or posting a comment / content of some sort.

The problem, however, has been with us ever since the POST verb was added to the HTTP protocol, 20 years ago: A web server is — by design and for really good reasons (which I won’t get into here; maybe some other time, probably in the form of a rant about JavaScript NoSQL implementations) — stateless.

You request a resource, the HTTP daemon sends a response, and that’s it. No long goodbyes, no phone calls in the morning just to see how you’re doing. It’s over; move on.

A Web server has no long-term memory. Calling the same URL from the same Web browser with the same payload, only a microsecond after a first request, still looks to a Web server like a brand-new thing. Again, because that’s the way it was made to work, and that’s the way it ought to work.

This, however, is not the case with PHP. The same practical reasons that make it desirable for a Web server to forget about you immediately make it really important for PHP to hold on to certain data, even if you don’t need it any more.

Sessions, for example. Or, in this case, the $_POST superglobal.

Superglobals Are Super-Hard To Kill

The PHP documentation tells us that a superglobal is “always available in all scopes.”

In layman’s terms, that means you can access $_POST anywhere in a given PHP script: The very first line, the very last line, inside a function, inside an included PHP file, inside a private final class member … everywhere and anywhere. Which is pretty awesome, except for when it’s not. Like, when you are trying to get PHP to dispose of that variable.

In short, PHP uses what is effectively a special kind of session to hold on to superglobals. Yes, that’s correct: Even if you haven’t explicitly instructed PHP to establish a session, any time you make a request that involves the creation or populating a superglobal, PHP makes its own, not-directly-accessible-by-code kind of session, to hold on to that superglobal.

Because this “session” is automagic, and because we cannot access it directly by code, destroying it is tricky.

In theory, we should be able to call unset on $_POST; the docs tell us that unset “destroys the specified variables.”

Oh, but then we scroll down, and scroll down some more, and some more. And we see that there are all sorts of caveats and conditions and context under which unset works; that the more complicated the scope of a variable proves, the less predictable unset proves.

And we are dealing with a superglobal: A variable intended to be omnipresent, and therefore necessarily hardy.

To get rid of a superglobal, we actually need PHP to jettison that special session it created. And the only effective way to do that is — just as with a basic Web server — create a whole new request.

But keep in mind, we’re talking about a fully developed, exceptionally extensible technology stack here. Which means that there are also workarounds we can employ; techniques or tricks that don’t force a new request / superglobals session, but which have the same net effect.

It’s that option we’ll discuss in Part 3 of this series. But first, Part 2: Server-side form validation.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  • Check out the Commenting Guidelines before commenting, please!
  • Want to share code? Please put it into a GitHub Gist, CodePen or pastebin and link to that in your comment.
  • Just have a line or two of markup? Wrap them in an appropriate SyntaxHighlighter Evolved shortcode for your programming language, please!