web-dev-qa-db-ja.com

PHPでHTTPキャッシュヘッダーを使用する方法

PHP 5.1.0のWebサイトがあります(実際には5.2.9ですが、5.1.0 +でも実行する必要があります)。

ページは動的に生成されますが、それらの多くはほとんど静的です。静的とは、コンテンツは変わらないことを意味しますが、コンテンツの周りの「テンプレート」は時間とともに変化する可能性があります。

私はそれらがいくつかのキャッシュシステムであり、PHPフレームワークが既に存在することを知っていますが、私のホストにはAPCまたはMemcachedがインストールされておらず、この特定のプロジェクトにフレームワークを使用していません。

ページをキャッシュしたい(デフォルトでPHP "disallow" cache)と思う。これまでのところ私は使用している:

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

私は多くのチュートリアルを読みましたが、単純なものは見つかりません(キャッシュは複雑なものですが、基本的なものだけが必要です)。

キャッシングを支援するために送信する必要のある「必須」ヘッダーとは何ですか?

59
AlexV

privateの代わりにprivate_no_expireを使用することもできますが、変更されないことがわかっているコンテンツには長い有効期限を設定し、if-modified-sinceおよびif-none-matchリクエストを処理するようにしてください。 Emilの投稿に似ています。

$tsstring = gmdate('D, d M Y H:i:s ', $timestamp) . 'GMT';
$etag = $language . $timestamp;

$if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : false;
$if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? $_SERVER['HTTP_IF_NONE_MATCH'] : false;
if ((($if_none_match && $if_none_match == $etag) || (!$if_none_match)) &&
    ($if_modified_since && $if_modified_since == $tsstring))
{
    header('HTTP/1.1 304 Not Modified');
    exit();
}
else
{
    header("Last-Modified: $tsstring");
    header("ETag: \"{$etag}\"");
}

$etagは、コンテンツまたはユーザーID、言語、タイムスタンプなどに基づくチェックサムです。

$etag = md5($language . $timestamp);
45
Steve-o

Expiresヘッダーが必要です。技術的には他のソリューションもありますが、有効期限が切れる前にページを再チェックせず、キャッシュからコンテンツを提供するようにブラウザーに指示するため、Expiresヘッダーは本当に最適です。本当に素晴らしいです!

ブラウザからのリクエストでIf-Modified-Sinceヘッダーを確認することも役立ちます。このヘッダーは、ブラウザのキャッシュ内のコンテンツがまだ正しいバージョンであるかどうかが不明な場合に送信されます。それ以降にページが変更されていない場合は、HTTP 304コードを送信します(変更なし)。 10分間304コードを送信する例を次に示します。

<?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;
  }
}
?>

サーバーリソースを節約するために、このチェックをコードの早い段階で行うことができます。

12
Emil Vikström
<?php
header("Expires: Sat, 26 Jul 2020 05:00:00 GMT"); // Date in the future
?>

キャッシュされたページの有効期限を設定することは、クライアント側でキャッシュするための便利な方法の1つです。

8
S Pangborn

あなたの選択を取る-またはそれらをすべて使用してください! :-)

 header( 'Expires:Thu、01-Jan-70 00:00:01 GMT'); 
 header( 'Last-Modified:'。gmdate( 'D、d MYH:i: s ')。' GMT '); 
 header(' Cache-Control:no-store、no-cache、must-revalidate '); 
 header(' Cache-Control:post-check = 0、事前チェック= 0 '、false); 
 header(' Pragma:no-cache '); 
7
Mike Foster

これは、HTTPキャッシングを行う小さなクラスです。 「Init」という静的関数があり、2つのパラメーター、ページ(またはブラウザーによって要求された他のファイル)が最後に変更された日付のタイムスタンプ、およびこのページを保持できる最大経過時間(秒)が必要です。ブラウザによるキャッシュ。

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
Jasper

Facebookフィードから来るサーバーでJSONキャッシュを実行していましたが、フラッシュを入れてエラー報告を隠すまで何も機能しませんでした。これは理想的なコードではないことは知っていますが、簡単な修正が必要でした。

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

これは非常にうまくいきました。

2
abksharma

これは、PHPキャッシュの最適なソリューションです。スクリプトの先頭でこれを使用するだけです。

$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");
0
Amit Ghosh Anto