Vinay Jeurkar
Vinay Jeurkar

Reputation: 3132

How to update browser cache from PHP?

I have a PHP file get_css.php which generates CSS code more than 60 KB long. This code does not change very often. I want this code to be cached in user's browser. Now, when i visit a HTML page several times which includes get_css.php url to fetch css, my browser is loading all CSS contents from the server each time i visit the page.

Browsers should get the contents from server only if the CSS code is changed on server side. If the css code is not changed, browser will use the css code from the browser cache. I cannot use any PHP function which is not allowed in Server Safe Mode.

Is it possible? How can i achieve this?

Upvotes: 0

Views: 1965

Answers (4)

Lee
Lee

Reputation: 13542

The browser wants to cache your document by default, but you have to give it enough info to make that possible. One fairly easy way is to send the Last-Modified header, containing the date/time at which your script was last changed. You'll also need to handle the browser's "revalidation" request correctly by checking the incoming Last-Modified date, comparing it to the actual modified date of your script, and returning a 304 Not Modified response (with an empty response body), if the file is unchanged.

It's also a good idea to be sure that your server isn't "magically" sending any other "no-cache" directives. The easiest way to do this is to send a Cache-Control directive that tells the browser exactly what behavior you expect.

Here is a quick explanation of each Cache-Control option.

Something like the following should do the trick:

<?php
// this must be at the top of your file, no content can be output before it

$modified = filemtime(__FILE__);
if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
  $if_modified_since=strtotime($_SERVER["HTTP_IF_MODIFIED_SINCE"]);
  if( $modified > $if_modified_since ) {
    header('HTTP/1.0 304 Not Modified');
    exit();
  }
}
header('Cache-Control: must-revalidate');
header('Last-Modified: '.date("r",$modified));

// ... and the rest of your file goes here...

The above example was based heavily on the example, and writeup found here.

Upvotes: 0

Bart Friederichs
Bart Friederichs

Reputation: 33573

You cannot control browser behaviour from PHP, but you can use HTTP codes to tell the browser something.

If the CSS is not changed, just reply with a 304 Not Modified response code:

if ($css_has_not_changed && $browser_has_a_copy) {
    http_response_code(304);
} else {
    // regenerate CSS
}

This way, the browser will ask for the document (which you cannot control), but you tell him to use the cached copy.

Of course this needs testing, as I have now idea how it will work 'the first time' a browser requests the file (perhaps the request headers can tell you more). A quick firebug test reveals that Firefox requests Cache-Control: no-cache when it is requesting a fresh copy, and Cache-Control: max-age=0 when it has cache.

Upvotes: 1

bear
bear

Reputation: 11625

You cannot force a client to revalidate its cache so easily.

Setting a variable query string to its resource won't play well with proxies, but seems to suffice with browsers. Browsers do tend to only redownload the css file if there's a query string change.

 <link rel="stylesheet" type="text/css" href="/get_css.php?v=1.2.3"> 

Potentially, you could play with the naming of the CSS, such as add numbers, but this isn't a great alternative.

Upvotes: 1

wormhit
wormhit

Reputation: 3837

add normal GET parameter when you including get_css.php like so

<link rel="stylesheet" type="text/css" href="get_css.php?v=1">

Browser will think that it is new link and will load it again.

and in get_css.php use this to make browser cache data

<?php
header("Content-type: text/css");
header('Cache-Control: public');
header('Expires: ' . gmdate('D, d M Y H:i:s', strtotime('+1 year')) . ' GMT');
ob_start("ob_gzhandler");

//echo css here

Upvotes: 0

Related Questions