5

毎回同じ $_GET パラメータで同じものを返す PHP ファイルがあります。これは決定論的です。

残念ながら効率のために (このファイルは非常に頻繁に要求されます)、Apache はデフォルトで PHP ページが要求されるたびに "200 OK" 応答を返すため、ユーザーはファイルを再度ダウンロードする必要があります。

パラメータが同じ場合にのみ304 Not Modifiedヘッダーを送信する方法はありますか?

おまけ: 有効期限を設定して、キャッシュされたページがたとえば 3 日以上経過している場合に "200 OK" 応答を送信することはできますか?

4

4 に答える 4

10

自分でページ (または少なくともその Etag) をキャッシュしないと、実際に 304 を利用することはできません。本格的なキャッシュ アルゴリズムはやや範囲外ですが、一般的な考え方は次のとおりです。

<?php 
function getUrlEtag($url){
    //some logic to get an etag, possibly stored in memcached / database / file etc.
}
function setUrlEtag($url,$etag){
    //some logic to get an etag, possibly stored in memcached / database / file etc.
}
function getPageCache($url,$etag=''){
    //[optional]some logic to get the page from cache instead, possibly not even using etag
}
function setPageCache($url,$content,$etag=''){
    //[optional]some logic to save the page to cache, possibly not even using etag
}
ob_start();
$etag = getUrlEtag($_SERVER['REQUEST_URI']);
if(isset($_SERVER['HTTP_IF_NONE_MATCH']) && trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) { 
    header("HTTP/1.1 304 Not Modified"); 
    exit; 
}
if(($content=getPageCache($_SERVER['REQUEST_URI'],$etag))!==false){
    echo $content;
    exit;
}
?>
//the actual page
<?php
$content = ob_get_clean();
setUrlEtag($_SERVER['REQUEST_URI'],$etag=md5($url.$content));
function setPageCache($_SERVER['REQUEST_URI'],$content,$etag);
header("Etag: $etag");
echo $content;
?>

すべての一般的な落とし穴が適用されます: ログインしているユーザーのキャッシュ ページを表示できない可能性がある、部分的なコンテンツのキャッシュがより望ましい可能性がある、キャッシュ内の古いコンテンツを防止する責任がある (変更時にバックエンドまたはデータベースでトリガーを使用する可能性がある、またはロジックで遊んでいるだけですgetUrlEtag)など

HTTP_IF_MODIFIED_SINCEそれが制御しやすい場合は、いじることもできます。

于 2010-06-05T00:30:41.460 に答える
8

一般に、Header 関数を使用して HTTP ステータス コードを返します。

Header("HTTP/1.1 304 Not Modified");
exit();

ただし、これだけでは不十分です。

問題は、ファイルがどのように要求されたかがわからないことです。そのため、ブラウザーの連携が少し必要になります。

受信リクエストでヘッダーを検索しIf-modified-since、存在し、日付範囲内にある場合は、適切なステータス コードを返すことができます。

最初に PHP を生成するときに適切なExpiresヘッダーを送信すると、ブラウザーまたはプロキシ キャッシュが要求をまったくフェッチしないと判断する場合があります (If-modified-sinceヘッダーを設定する可能性の方が高いですが)。ヘッダーがないExpires場合、ブラウザは常にリクエスト全体を再試行する可能性があります。

詳細については、http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.htmlを参照して、「14.25」を検索してください。

GETブラウザは、キャッシュされたコピーへのパラメータのマッピングを行います。そこで作業を行う必要はありません。

于 2010-06-05T00:05:11.080 に答える
2

呼び出されている PHP コードを試しheader("HTTP/1.0 304 Not Modified");ましたか? 慣れていない場合は、バッファに何かを出力し始める前に、コードにそれを入れたいと思うでしょう。

http://php.net/manual/en/function.header.php

于 2010-06-05T00:05:04.713 に答える