PHP ile HTTP önbellek başlıklarını nasıl kullanılır

6 Cevap php

Ben bir PHP 5.1.0 web sitesi var (aslında 5.2.9 ama aynı zamanda 5.1.0 + çalıştırmak gerekir).

Sayfaları dinamik olarak oluşturulan ancak birçoğu çoğunlukla statik vardır. Statik tarafından ben içerik değişiklik yok ama içerik etrafında "şablon" zamanla değişebilir anlamına gelir.

Ben zaten orada birkaç önbellek sistemleri ve PHP çerçeveler olduğunu biliyorum, ama benim ana APC veya Memcached yüklü yok ve ben bu özel proje için herhangi bir çerçeve kullanarak değilim.

Ben sayfaları (I varsayılan PHP "yasaklılar" önbellek düşünüyorum) önbelleğe alınmasını istiyorum. Bugüne kadar ben kullanıyorum:

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

Ben birçok öğreticiler okumak ama ben (cache karmaşık bir şey olduğunu biliyorum, ama sadece bazı temel şeyler gerekir) basit bir şey bulamıyorum.

Önbelleğe yardım göndermek için başlıkları ne var "olmalı" vardır?

Teşekkürler!

6 Cevap

Sen private_no_expire yerine private kullanımı, ama değiştirmek ve {emin if-modified-since işlemek yapmak ve gitmiyor biliyorum içerik için uzun bir süre sonunu ayarlamak isteyebilirsiniz [(3)]} Emil'in mesaja benzer istekleri.

$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}\"");
}

Nerede $etag, örneğin içeriğine dayalı bir sağlama ya da kullanıcı kimliği, dili ve zaman damgası, olabilir

$etag = md5($language . $timestamp);

Sen Expires başlığını olmalıdır. Teknik olarak, orada başka çözümler vardır, ancak bu son kullanma tarihi ve saatinden önce sayfayı yeniden kontrol ve sadece önbellekten içeriği değil hizmet için tarayıcı söyler çünkü başlık, gerçekten orada iyi biridir Bitiş. Bu gerçekten harika çalışıyor!

Bu tarayıcı isteği bir If-Modified-Since başlık için kontrol etmek için de yararlıdır. Bu önbelleğinde içeriği hala doğru versiyon ise tarayıcı "emin" olduğunda bu başlık gönderilir. Sayfanızı o zamandan beri değiştirilmiş ise, sadece bir HTTP 304 kodu (Değişmedi) geri göndermek. İşte Apache üzerinde çalışır ve on dakika boyunca bir 304 kodu gönderen bir örnek:

<?php
$headers = apache_request_headers();
if(isset($headers['If-Modified-Since'])) {
  if(strtotime($headers['If-Modified-Since']) < time() - 600) {
    header('HTTP/1.1 304 Not Modified');
    exit;
  }
}
?>

Sen sunucu kaynaklarını kaydetmek için kod erken bu denetimi koyabilirsiniz.

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

Önbelleğe alınan sayfa için bir son kullanma tarihi ayarlama istemci tarafında önbelleğe bir yoldur.

Seçiminizi yapın - ya da hepsini kullanın! :-)

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');

İşte sizin için http önbelleğe alma yapan bir küçük sınıf bulunuyor. Bu sayfayı tutulabilir ki, saniyede 2 parametreleri, sayfa (ya da tarayıcı tarafından istenen herhangi bir diğer dosya) son düzenleme olduğu tarih damgası ve yaş sınırını, ihtiyacı 'Init' adında bir statik işlevi vardır tarayıcı tarafından önbellek.

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

I was doing json caching at the server coming from facebook feed nothing was working untill I put flush and hid error reporting. I know this the demon code but wanted a quick fix asap.

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

Cazibe gibi çalıştı.