I struggled for a number of hours trying to figure out why IE was caching pages that were being dynamically generated. I was going crazy -- no matter what I did, it would still cache the page. Finally, I solved the problem after combing through numerous email and discussion list posts from other frustrated users. Hopefully this mini-article will solve some problems...

First, some background: The system I'm building uses phplib7 and php4. I use Tim's trick to ensure URLs are searchable via the .htaccess <Files> method (see the article on build sites with search engines in mind).

It appears as if IE will cache a document based on the full URL -- including stuff after the ?. So if the URL remains the same but the content changes (and the stuff after the ? is the same too) then IE will load the page from the cache. Using Tim's hack, where there's no need for a ? anywhere, this becomes immediately obvious.

My first attempt at a solution was to send out a bunch of headers. After excessive experimentation, I determined that the following headers were sufficient:

header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-cache");
header("Cache-Control: post-check=0,pre-check=0");
header("Cache-Control: max-age=0");
header("Pragma: no-cache");

These headers will stop IE from caching your dynamic pages. You may be able to do without some of the lines, but then other browsers might start caching your pages.

BUT, and here's the kicker -- if you're using PHPLib session code, it will also attempt to send out some of these headers. The way in which the headers are sent is not determined by PHP -- it's determined by Apache. If your headers conflict with the PHPLib headers IE will get a confused set of headers and will pull the doc from cache. This was basically the root of my agony -- I was trying to set the headers in my code explicity, but PHPlib was sending a slightly different version of the headers. I didn't check to see what IE was finally getting, but whatever it was didn't do the trick.

So, if you are using PHPlib, I suggest the following:

In your local.inc file where you subclass Session, overload the put_headers() method. Copy the put_headers method directly from the Session class, but add the following:

case "iehack":
 header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); 
 header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
 header("Cache-Control: no-cache");
 header("Cache-Control: post-check=0,pre-check=0");
 header("Cache-Control: max-age=0");
 header("Pragma: no-cache");
break;

just before the default: tag.

Now add the line:

var $allowcache = "iehack";

In your class definition and you should be good to go. Any page that uses the session code should send the proper headers. Just make sure that you're not setting headers anywhere else... and as always, check for blank lines at the end of your include files -- especially any includes that might get called BEFORE the phplib session code. These blank lines will case PHP to send out standard HTTP headers and the session headers will not take.

Hope this helps ....

Wes Sonnenreich