2009-12-28 31 views
51

Tôi có một trang web 5.1.0 PHP (thực sự là 5.2.9 nhưng nó cũng phải chạy trên 5.1.0+).Cách sử dụng tiêu đề bộ nhớ cache HTTP với PHP

Trang được tạo động nhưng nhiều trang chủ yếu là tĩnh. Bởi tĩnh tôi có nghĩa là nội dung không thay đổi nhưng "mẫu" xung quanh nội dung có thể thay đổi theo thời gian.

Tôi biết chúng là một số hệ thống bộ nhớ cache và khung công tác PHP đã tồn tại, nhưng máy chủ của tôi không có APC hoặc Memcached được cài đặt và tôi không sử dụng bất kỳ khung công tác nào cho dự án cụ thể này.

Tôi muốn các trang được lưu vào bộ nhớ cache (tôi nghĩ theo mặc định là PHP "không cho phép" bộ nhớ cache). Cho đến nay tôi đang sử dụng:

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

Tôi đọc nhiều hướng dẫn nhưng tôi không thể tìm thấy điều gì đơn giản (tôi biết bộ nhớ cache phức tạp nhưng tôi chỉ cần một số nội dung cơ bản).

"Phải" có tiêu đề để gửi để trợ giúp bộ đệm ẩn là gì?

Cảm ơn!

+5

Chào mừng bạn đến với StackOverflow. Câu hỏi đầu tiên tuyệt vời! – Sampson

Trả lời

40

Bạn có thể muốn sử dụng private_no_expire thay vì private, nhưng thiết lập thời hạn dài cho nội dung mà bạn biết sẽ không thay đổi và chắc chắn rằng bạn xử lý if-modified-sinceif-none-match yêu cầu tương tự như bài Emil của.

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

Trường hợp $etag có thể là tổng kiểm dựa trên nội dung hoặc ID người dùng, ngôn ngữ và dấu thời gian, ví dụ:

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

Những gì bạn đã mô tả sẽ là một E-Tag yếu và phải có tiền tố "W /". –

+0

Tôi cũng sẽ thêm tiêu đề "Hết hạn", vì một số nhà cung cấp dịch vụ lưu trữ (ví dụ: máy chủ) vẫn gửi nó và họ thực hiện theo cách quay trở lại trước đây trong quá khứ, trong khi tôi nghĩ rằng nó sẽ là trong tương lai. – Sasho

+5

Nếu bạn không nhận được 304 với những điều trên, hãy kiểm tra không có bất kỳ dấu trích dẫn nào trong HTTP_IF_NONE_MATCH. Thay thế '$ if_none_match == $ etag' bằng' rtrim (ltrim ($ if_none_match, "'\" "),"' \ "") == $ etag' để chắc chắn. – ReactiveRaven

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

Đặt ngày hết hạn cho trang được lưu trong bộ nhớ cache là một cách hữu ích để lưu nó vào phía máy khách.

+0

Tốt và việc sử dụng session_cache_limiter và session_cache_expire đã được xử lý cẩn thận. – AlexV

6

Chọn lựa - hoặc sử dụng tất cả! :-)

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

session_cache_limiter và session_cache_expire đã kiểm soát hết hạn, Cache-Control, Last-Modified và Pragma ... – AlexV

+0

Tôi hiểu. Vâng, bạn nói đúng. Và tôi cũng thấy rằng tôi đã không đọc câu hỏi của bạn đủ tốt. xin lỗi –

11

Bạn phải có tiêu đề hết hạn. Về mặt kỹ thuật, có các giải pháp khác, nhưng tiêu đề hết hạn thực sự là giải pháp tốt nhất, vì nó yêu cầu trình duyệt không kiểm tra lại trang trước ngày hết hạn và chỉ phân phát nội dung từ bộ nhớ cache. Nó hoạt động thực sự tuyệt vời!

Cũng rất hữu ích khi kiểm tra tiêu đề If-Modified-Since trong yêu cầu từ trình duyệt. Tiêu đề này được gửi khi trình duyệt "không chắc chắn" nếu nội dung trong bộ nhớ cache của nó vẫn là phiên bản phù hợp. Nếu trang của bạn không được sửa đổi kể từ thời điểm đó, chỉ cần gửi lại mã HTTP 304 (Không được sửa đổi). Dưới đây là ví dụ gửi mã 304 trong mười phút:

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

Bạn có thể đặt séc này sớm trong mã để lưu tài nguyên máy chủ.

+0

Điều này là không tốt nếu bạn không sử dụng apache. – Geoffrey

2

Tôi đã thực hiện lưu bộ nhớ đệm json tại máy chủ đến từ nguồn cấp dữ liệu facebook không có gì hoạt động cho đến khi tôi đặt báo cáo lỗi xóa và xóa. Tôi biết mã ma quỷ này nhưng muốn có bản sửa lỗi nhanh.

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 

LÀM VIỆC như quyến rũ.

+1

Nó có thể không hoạt động nếu bạn không đặt tên trường $ headers ['If-Modified-Since'] thành chữ hoa -> $ headers ['IF-MODIFIED-SINCE] –

6

Đây là một lớp nhỏ thực hiện bộ nhớ đệm http cho bạn. Nó có chức năng tĩnh gọi là 'Init' cần 2 tham số, dấu thời gian của ngày mà trang (hoặc bất kỳ tệp nào khác do trình duyệt yêu cầu) được sửa đổi lần cuối và độ tuổi tối đa, tính bằng giây, trang này có thể được giữ trong bộ nhớ cache của trình duyệt.

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

Cảm ơn !! –

Các vấn đề liên quan