Caching PHP-generated pages (posted 2013-07-18)
For years, I always used to include an If-Modified-Since header in my PHP scripts in order to allow their output to be cached by web browsers. Turns out, it takes a bit more work.
The idea is that the HTTP server tells browsers when the page was last modified when browsers request a page. Then, when they request the same page again later, the browser can say "only send me the page if it's been modified since <date>". If the page has been changed since <date> the server sends over the page. If the page is still the same, it just sends a 304 response code, "Not Modified". The browser then displays the page from its cache.
(If the browser doesn't supply an If-Modified-Since date, the page is always sent.)
The Apache HTTP server can handle all of this for HTML and other static files. But PHP scripts generate output on the fly, so the concept of a last modified date doesn't really apply, so PHP-generated pages are always sent, even if they are the same as during an earlier visit.
Of course many PHP scripts generate output based on what's in a database, and as long as the contents of that database don't change, there's really no need to run the script again. But the script itself has to be smart enough to handle this. I had a look at this page and then came up with the following.
First, we determine what the last modified date should be: the last time the script itself was changed, or the last time the database was changed, whichever was more recent:
Then, we check against the If-Modified-Since header supplied by the browser. If the our last modified date is older or the same as the browser's, we send the Not Modified response and call it a day.
(Of course there's some more error checking here and there.)
If the script is still running, the browser had an old version of the page so we're going to send over the latest version. Before we do that, we generate a Last-Modified date so the browser knows what to say in its If-Modified-Since header the next time.
In Safari, it looks like entering a URL in the URL/search bar doesn't use If-Modified-Since, but clicking on a link does. This is now a good deal faster for me. It should help even more for people on slow links or far away from the server.