How to use HTTP cache headers with PHP

2020-01-23 04:40发布

I have a PHP 5.1.0 website (actually it's 5.2.9 but it must also run on 5.1.0+).

Pages are generated dynamically but many of them are mostly static. By static I mean the content don't change but the "template" around the content can change over time.

I know they are several cache systems and PHP frameworks already out there, but my host don't have APC or Memcached installed and I'm not using any framework for this particular project.

I want the pages to be cached (I think by default PHP "disallow" cache). So far I'm using:

session_cache_limiter('private'); //Aim at 'public'
session_cache_expire(180);
header("Content-type: $documentMimeType; charset=$documentCharset");
header('Vary: Accept');
header("Content-language: $currentLanguage");

I read many tutorials but I can't find something simple (I know cache is something complex, but I only need some basic stuff).

What are "must" have headers to send to help caching?

标签: php http caching
7条回答
你好瞎i
2楼-- · 2020-01-23 05:15

This is the best solution for php cache Just use this in the top of the script

$seconds_to_cache = 3600;
$ts = gmdate("D, d M Y H:i:s", time() + $seconds_to_cache) . " GMT";
header("Expires: $ts");
header("Pragma: cache");
header("Cache-Control: max-age=$seconds_to_cache");
查看更多
Fickle 薄情
3楼-- · 2020-01-23 05:17

I was doing JSON caching at the server coming from Facebook feed nothing was working until I put flush and hid error reporting. I know this is not ideal code, but wanted a quick fix.

error_reporting(0);
    $headers = apache_request_headers();
    //print_r($headers);
    $timestamp = time();
    $tsstring = gmdate('D, d M Y H:i:s ', $timestamp) . 'GMT';
    $etag = md5($timestamp);
    header("Last-Modified: $tsstring");
    header("ETag: \"{$etag}\"");
    header('Expires: Thu, 01-Jan-70 00:00:01 GMT');

    if(isset($headers['If-Modified-Since'])) {
            //echo 'set modified header';
            if(intval(time()) - intval(strtotime($headers['IF-MODIFIED-SINCE'])) < 300) {
              header('HTTP/1.1 304 Not Modified');
              exit();
            }
    }
    flush();
//JSON OP HERE

This worked very well.

查看更多
Viruses.
4楼-- · 2020-01-23 05:19

You must have an Expires header. Technically, there are other solutions, but the Expires header is really the best one out there, because it tells the browser to not recheck the page before the expiration date and time and just serve the content from the cache. It works really great!

It is also useful to check for a If-Modified-Since header in the request from the browser. This header is sent when the browser is "unsure" if the content in it's cache is still the right version. If your page is not modified since that time, just send back an HTTP 304 code (Not Modified). Here is an example that sends a 304 code for ten minutes:

<?php
if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
  if(strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) < time() - 600) {
    header('HTTP/1.1 304 Not Modified');
    exit;
  }
}
?>

You can put this check early on in your code to save server resources.

查看更多
可以哭但决不认输i
5楼-- · 2020-01-23 05:21

Take your pick - or use them all! :-)

header('Expires: Thu, 01-Jan-70 00:00:01 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
查看更多
乱世女痞
6楼-- · 2020-01-23 05:26

Here's a small class that does http caching for you. It has a static function called 'Init' that needs 2 parameters, a timestamp of the date that the page (or any other file requested by the browser) was last modified and the maximum age, in seconds, that this page can be held in cache by the browser.

class HttpCache 
{
    public static function Init($lastModifiedTimestamp, $maxAge)
    {
        if (self::IsModifiedSince($lastModifiedTimestamp))
        {
            self::SetLastModifiedHeader($lastModifiedTimestamp, $maxAge);
        }
        else 
        {
            self::SetNotModifiedHeader($maxAge);
        }
    }

    private static function IsModifiedSince($lastModifiedTimestamp)
    {
        $allHeaders = getallheaders();

        if (array_key_exists("If-Modified-Since", $allHeaders))
        {
            $gmtSinceDate = $allHeaders["If-Modified-Since"];
            $sinceTimestamp = strtotime($gmtSinceDate);

            // Can the browser get it from the cache?
            if ($sinceTimestamp != false && $lastModifiedTimestamp <= $sinceTimestamp)
            {
                return false;
            }
        }

        return true;
    }

    private static function SetNotModifiedHeader($maxAge)
    {
        // Set headers
        header("HTTP/1.1 304 Not Modified", true);
        header("Cache-Control: public, max-age=$maxAge", true);
        die();
    }

    private static function SetLastModifiedHeader($lastModifiedTimestamp, $maxAge)
    {
        // Fetching the last modified time of the XML file
        $date = gmdate("D, j M Y H:i:s", $lastModifiedTimestamp)." GMT";

        // Set headers
        header("HTTP/1.1 200 OK", true);
        header("Cache-Control: public, max-age=$maxAge", true);
        header("Last-Modified: $date", true);
    }
}
查看更多
手持菜刀,她持情操
7楼-- · 2020-01-23 05:34
<?php
header("Expires: Sat, 26 Jul 2020 05:00:00 GMT"); // Date in the future
?>

Setting an expiration date for the cached page is one useful way to cache it on the client side.

查看更多
登录 后发表回答