Last-Modified Header Ignored in Dynamic PHP Application when using session_cache_limiter for Cache

Doug Braun
3 min readDec 21, 2016

We were adding caching to a PHP application which dynamically generates all pages from database content.

The application already used sessions so we added the appropriate calls to session_cache_limiter(‘public’) and session_cache_expire(N) before the session_start invocation as required.

The appropriate Cache-Control and Expires HTTP headers started to be generated and their parameters were exactly what was expected.

In addition, a Last-Modified header was also being generated. But it’s time-stamp was a date from 2006 (10 years ago). That’s strange. Where did this date come from when all of the page content is dynamically generated?

We tried generating our own header(“Last-Modified: $timestamp GMT”, true) but this header was just ignored. We tried generating this header before the session_cache_limiter and session_cache_expire calls, or after them, but in all cases it was ignored and didn’t alter the outcome. The 10 year old Last-Modified header is what the client browsers were still receiving.

We finally determined that the date was coming from the wrapper index.php file that invokes the application. It basically has two lines of code in it to require_once a class file and then to call it, which starts the application running. This wrapper file hasn’t been changed in 10 years.

We tried disabling any PHP generated Last-Modified header by using ini_set(‘last_modified’,0). It was already disabled by default and this didn’t change anything.

The PHP documentation for session_cache_limiter says the following about the automatic generation of this header:

“Last-Modified: (the timestamp of when the session was last saved)”

The wording is strange since the session_cache_limiter must be called before session_start, so there is no session yet so how can the timestamp be related to when the non-existent session was last saved?

We could not find any way to pass or affect the timestamp that was used in the Last-Modified header that was generated from session_cache_limiter.

Then we figured it out.

The session_cache_limiter and session_cache_expire functions don’t generate any headers themselves; they set parameters that the session_start function uses when it generates all of the associated headers. This is the reason why these two functions need to be called before session_start. It is session_start which actually generates the headers (e.g. Cache-Control, Expires, Last-Modified, etc.).

Once we knew this, the solution was simple. Just move the Last-Modified header function after the session_start function and include “true” as it’s optional second parameter to override any previous header of the same name. This replaced the Last-Modified header that was auto-generated by session_start with the manual header we wanted to use.

It was all just about the order of the statements:

  • session_cache_limiter(‘public’);
  • session_cache_expire($expire_minutes);
  • session_start();
  • header( “Last_Modified: “.gmdate(‘D, d M Y H:i:s’,$timestamp).” GMT”, true);

I hope this information helps someone who encounters a similar issue in getting their desired Last-Modified date to be used in a dynamic PHP application.

Found this post useful? Kindly tap the ❤ button below! :)

--

--

Doug Braun

Dad, entrepreneur, IT architect, problem solver — always learning. Love new technology, cycling, strong coffee, outer space, and helping those in need.