Separation of POST/GET requests in PHP

June 18, 2007 on 4:26 pm | In PHP, Web apps |

Last time we talked about MVC application design. There is something I want to write about, stemming from the topic of the last article. It is the separation of POST/GET requests in PHP web apps, which I am an advocate of. It is sort of like a VC (View-Controller) architecture.

This is strictly an application-design topic. I’m not introducing any new fancy functions or features in PHP. It’s about how you design your web app, for better usability. (I happen to be pretty serious about web app usability, which, IMO, all software developers should be, for any software they are working on. This is why so many of my articles focus on what you could do to improve usability — it’s something too many programmers neglect.)

The history of HTTP’s POST and GET requests

I’m sure almost anyone who does web development know what POST and GET requests are. GET requests include form parameters in the query string of the request; they can get cached; they can be sent to a friend through email/IM, and so on. POST requests send parameters as part of the header in the request, and are not visible. However, when you come down to the basic technical operations, they work almost the same way: you can do just about anything you could in either method in the other one as well. (multi-part form data are a bit harder on GET, but it could be do-able)

The most important difference, actually, lies in the definitions — when these HTTP requests were first invented. A POST request is defined to be a request to the server that changes the state of the server. This means, for example, posting a message on a forum, uploading a file, or anything at all that changes (inserts/deletes/updates) the database, the file system, or anything else. A GET request, on the other hand, is defined as a way to retrieve information from the server without making any changes, or a “query” as they call it.

Why does it all matter?

Knowing the history of POST and GET requests, you should also be aware that browsers like Firefox and IE are designed with this in mind. When you attempt to Refresh a page (or going Back/Forward to it) that you got from POSTing a form, you get a warning box telling you that POST data will be sent again to the server. This is because a POST request is expected to make a change, and repeating the same request just to view the resulting page is usually not what the users intend to do, or what the developers intend for the users to do.

Unfortunately, on the users point-of-view, this creates a very user-unfriendly situation when web apps aren’t designed with this in mind. The average internet user does not know the difference between POST and GET requests (many won’t even be able to tell what an HTML form is), but web developers assume people know what they are doing. Your job, as a web developer, is to make it as less painful as an experience for web users as possible. Back and Forward buttons are the most commonly used features by web users, and you want to design something that works with them, not against them. This is why I’m an advocate of separating POST and GET requests in PHP.

What do you mean by separating POST and GET requests?

It might not be the best way to phrase it. What I mean is to make only GET requests display anything at all, and POST requests results should always redirect to another page in the form of a GET request. In other words, POST requests always only get sent to “Controller” scripts, while GET requests always only get sent to “View” scripts.

To make this easier to understand, I will take the example of a project I have done a few years ago, designed in this method. It is a web-based file manager that lets you upload, delete, rename, move files as well as folders.

No AJAX was used in this application (it wasn’t popular in 2003). All actions are sent as a new POST request to a PHP script on the server. However, there really is only one script file for the “view”, called main.php. A handful of other PHP scripts handle all the different actions. When you upload a file, a request is sent to upload.php, and this script will redirect back to main.php in the end, using a Location header.

To handle error messages (or success messages), I use cookies. Back to the uploading example again — before redirecting to main.php, I set a cookie with the status and message. In main.php, if a cookie is found with this information, a dialogue box displays with the message, and then the cookie gets cleared.

Designed this way, Back and Forward buttons may be used freely without actually corrupting the state of the server. It is true that, for example, if a page was cached, hitting Back may lead you to an old page — but at least the POST request wouldn’t be sent again (as POST is what makes changes to the server). Most of the time, implementing some sort of cache-stopping mechanism can stop this from happening. In my file manager example, even dialogue boxes work correctly (would not re-display after showing once), due to the use of cookies.

Some final notes

If you are interested in some additional reading, you can look at the official HTTP/1.1 method definitions. An interesting part of it is this:

The action performed by the POST method might not result in a resource that can be identified by a URI. In this case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on whether or not the response includes an entity that describes the result.

If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header (see section 14.30).

It looks like that you should be returning a status code of 201 if you are going to redirect to another page using a GET request, after doing your processing in your POST request. I’m actually not entirely sure what benefits do you get from doing that other than being politically correct about definitions. If anyone knows the answer to this, feel free to post a reply and enlighten me. :)

No Comments yet »

RSS feed for comments on this post. TrackBack URI

Leave a comment

You must be logged in to post a comment.

Powered by WordPress with Pool theme design by Borja Fernandez. Entries and comments feeds. Valid XHTML and CSS. ^Top^