วิธีป้องกัน Browser cache สำหรับ php site


121

ฉันมีไซต์ php ที่ทำงานในเซิร์ฟเวอร์คลาวด์เมื่อฉันเพิ่มไฟล์ใหม่ css, js หรืออิมเมจเบราว์เซอร์จะโหลดไฟล์ js, css และรูปภาพเดิมที่เก็บไว้ในแคช

ไซต์ของฉันมีประเภทหลักและเมตาแท็กดังต่อไปนี้

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  <meta http-equiv="Page-Enter" content="blendTrans(Duration=1.0)">
  <meta http-equiv="Page-Exit" content="blendTrans(Duration=1.0)">
  <meta http-equiv="Site-Enter" content="blendTrans(Duration=1.0)">
  <meta http-equiv="Site-Exit" content="blendTrans(Duration=1.0)">

เนื่องจากประเภทด้านบนและรหัสเมตาฉันจึงโหลดไฟล์เดียวกันที่แคชไว้ในเบราว์เซอร์แทนที่จะเป็นไฟล์ใหม่


No Cache in all Browsers. คุณยังสามารถทำ? randomGeneratedNumber ในไฟล์ที่คุณไม่ต้องการแคช
Kodemon

2
คุณอาจไม่ต้องการปิดการใช้งานแคชอย่างสมบูรณ์สำหรับรูปภาพ / js / css: stackoverflow.com/questions/4206224/…
FoolishSeth

ต่อต้านการล่อลวงเพื่อเนโคร แต่ได้โปรดทุกคนที่พิจารณาสิ่งนี้: หยุด เรียนรู้ที่จะควบคุมและใช้การแคชอย่าเพิ่งปิดการใช้งานแบบสุ่มสี่สุ่มห้าเพราะตอนเดียวที่ไม่สะดวก อ่านบทเกี่ยวกับการแคชจากHTTP The Definitive Guide - หนังสือเล่มนี้ (และ RFCs) ควรเป็นหนังสือบังคับพร้อมแบบทดสอบ เรียนรู้วิธีระบุ Last-Modified ตอบสนองต่อ If-Modified-Since และใช้การระบุ ETag จากนั้นเมื่อมีการอัปเดตเนื้อหาเบราว์เซอร์จะได้รับแจ้งเมื่อ 304 กลายเป็น 200 อีกครั้ง
amcgregor

คำตอบ:


283

ลองดู

<?php

header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
?>

6
ยกเว้น "max-age = 0" ซึ่งเป็นส่วนหัวที่ PHP ส่งมาโดยไม่ได้ระบุข้างต้นในการติดตั้งของฉันดูเหมือนว่า PHP พยายามป้องกันการแคชเบราว์เซอร์โดยค่าเริ่มต้น ...
ตอบสนองอย่างรวดเร็ว

1
ฉันมีปลั๊กอิน WordPress ที่ส่งธีมทางเลือกไปยัง Internet Explorer เวอร์ชันเก่าและระบบแคชบางระบบสะดุด โพสต์นี้เกิดขึ้นจากการค้นหาโดย Google ครั้งแรกของฉัน เล่นดี.
จำเป็น

3
โปรดทราบว่าสิ่งนี้ไม่สามารถฝังอยู่ใน html ได้ ควรอยู่ที่ด้านบนสุดของหน้า
Hunter S

9
หมายเหตุ: หากคุณใช้session_start()หลังจากนั้นมันจะเขียนทับส่วนหัวของคุณด้วยCache-Control: private, max-age=10800, pre-check=10800เนื่องจาก 180 นาทีเป็นค่าเริ่มต้นของsession.cache_expire. ถ้าคุณไม่สามารถหลีกเลี่ยงการเริ่มต้นเซสชั่น session_cache_limiter('private');session_cache_expire(0);แต่คุณจำเป็นต้องปิดการใช้แคช
mgutt

2
@thdoan พารามิเตอร์ที่สองของheaderฟังก์ชั่นเป็นแบบบูลสำหรับแทนที่ พารามิเตอร์การแทนที่ทางเลือกระบุว่าส่วนหัวควรแทนที่ส่วนหัวที่คล้ายกันก่อนหน้านี้หรือไม่หรือเพิ่มส่วนหัวที่สองของประเภทเดียวกัน
mrReiha

36

ที่นี่หากคุณต้องการควบคุมผ่าน HTML: ทำตามตัวเลือกที่ 1ด้านล่าง:

<meta http-equiv="expires" content="Sun, 01 Jan 2014 00:00:00 GMT"/>
<meta http-equiv="pragma" content="no-cache" />

และหากคุณต้องการควบคุมผ่าน PHP: ให้ทำดังนี้ตัวเลือกที่ 2:

header('Expires: Sun, 01 Jan 2014 00:00:00 GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', FALSE);
header('Pragma: no-cache');

และตัวเลือกที่ 2 จะดีกว่าเสมอเพื่อหลีกเลี่ยงปัญหาการแคชตามพร็อกซี


10

คุณสามารถลองสิ่งนี้:

    header("Expires: Tue, 03 Jul 2001 06:00:00 GMT");
    header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
    header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
    header("Cache-Control: post-check=0, pre-check=0", false);
    header("Pragma: no-cache");
    header("Connection: close");

หวังว่ามันจะช่วยป้องกัน Cache ได้ถ้ามี!


สิ่งนี้เกี่ยวข้องกับการแคชไฟล์ HTML เท่านั้นใช่ไหม และไม่มีส่วนเกี่ยวข้องกับ eTag? ขอบคุณ!
Sam Levin

4
เพียงแค่บรรทัดแรกก็เพียงพอแล้ว บรรทัดที่ 5 นั้นผิดจริง ๆ และไม่มีอะไรทำในการตอบกลับของเซิร์ฟเวอร์ (เป็นส่วนหัวของคำขอ) บรรทัดที่หกจะไม่มีผลกระทบต่อสิ่งที่เกิดขึ้น ฉันจะไปต่อ ...
The Surrican

วิธีการใช้ปืนลูกซอง: โยนทุกอย่างไปที่กำแพงหวังว่าจะมีบางสิ่งติดอยู่ ตามความคิดเห็นของฉันเกี่ยวกับคำถามนั้นฉันขอแนะนำให้คุณจับสำเนาHTTP: The Definitive Guideและอ่านบทเกี่ยวกับ Caching RFC ด้วย แต่การอ่านสิ่งเหล่านี้เป็นทักษะที่แตกต่าง ("การเชื่อมต่อ: ปิด" เป็นการยิงด้วยเท้าแบบฮา ๆ ที่จะรวมไว้ปิดการใช้งานการส่งไปป์ไลน์ที่มีประสิทธิภาพหรือไม่ทำอะไรเลย แต่ฉันสงสัยว่า PHP อาจปล่อยให้ผ่านไปได้)
amcgregor

7

ฉันมีปัญหากับการแคชไฟล์ css ของฉัน การตั้งค่าส่วนหัวใน PHP ไม่ได้ช่วยฉัน (อาจเป็นเพราะต้องตั้งค่าส่วนหัวในไฟล์สไตล์ชีทแทนที่จะเป็นหน้าที่ลิงก์ไป)

ฉันพบวิธีแก้ปัญหาในหน้านี้: https://css-tricks.com/can-we-prevent-css-caching/

การแก้ไขปัญหา:

ผนวกการประทับเวลาเป็นส่วนการสืบค้นของ URI สำหรับไฟล์ที่ลิงก์
(สามารถใช้สำหรับ css, js, รูปภาพ ฯลฯ )

สำหรับการพัฒนา:

<link rel="stylesheet" href="style.css?<?php echo date('Y-m-d_H:i:s'); ?>">

สำหรับการผลิต (โดยที่การแคชส่วนใหญ่เป็นสิ่งที่ดี):

<link rel="stylesheet" type="text/css" href="style.css?version=3.2">
(และเขียนใหม่ด้วยตนเองเมื่อจำเป็น)

หรือการรวมกันของทั้งสอง:

<?php
    define( "DEBUGGING", true ); // or false in production enviroment
?>
<!-- ... -->
<link rel="stylesheet" type="text/css" href="style.css?version=3.2<?php echo (DEBUGGING) ? date('_Y-m-d_H:i:s') : ""; ?>">

แก้ไข:

หรือการรวมกันที่สวยกว่าของทั้งสอง:

<?php
    // Init
    define( "DEBUGGING", true ); // or false in production enviroment
    // Functions
    function get_cache_prevent_string( $always = false ) {
        return (DEBUGGING || $always) ? date('_Y-m-d_H:i:s') : "";
    }
?>
<!-- ... -->
<link rel="stylesheet" type="text/css" href="style.css?version=3.2<?php echo get_cache_prevent_string(); ?>">

เวอร์ชันตามอำเภอใจการประทับเวลาปัจจุบัน (เอาชนะการแคชทั้งหมด) ... แต่ไม่ใช่สิ่งเดียวที่สมเหตุสมผลและใช้ได้ผลไม่ว่าจะมีการตั้งค่าสถานะ "การแก้ไขข้อบกพร่อง" หรือไม่ก็ตาม ทำไมคุณไม่ใช้ mtime จริงของไฟล์? จากนั้นคุณไม่จำเป็นต้องอัปเดต PHP และแคชจะไม่กลายเป็นสิ่งที่ไร้ประโยชน์อย่างสมบูรณ์ หรือเพียงแค่ส่งสถิตของคุณด้วยเซิร์ฟเวอร์ HTTP ที่กำหนดค่าไว้อย่างเหมาะสมเช่น Nginx หรือ Apache ที่ตั้งค่า Last-Modified และ ETag ที่เหมาะสม ในทำนองเดียวกันการตั้งค่าสถานะ "การดีบัก" ประเภทนั้นมีอยู่แล้ว ... ในเบราว์เซอร์ (ปิดการใช้งานแคชรีเฟรชโดยไม่ใช้แคชแคชว่าง ... )
amcgregor

5

การป้องกันแคชของเบราว์เซอร์ไม่ใช่ความคิดที่ดีขึ้นอยู่กับกรณี กำลังมองหาวิธีแก้ปัญหาฉันพบวิธีแก้ปัญหาดังนี้:

<link rel="stylesheet" type="text/css" href="meu.css?v=<?=filemtime($file);?>">

ปัญหาคือถ้าไฟล์ถูกเขียนทับในระหว่างการอัพเดตบนเซิร์ฟเวอร์ซึ่งเป็นสถานการณ์ของฉันแคชจะถูกละเว้นเนื่องจากการประทับเวลาถูกแก้ไขแม้ว่าเนื้อหาของไฟล์จะเหมือนกันก็ตาม

ฉันใช้วิธีนี้เพื่อบังคับให้เบราว์เซอร์ดาวน์โหลดเนื้อหาก็ต่อเมื่อมีการแก้ไขเนื้อหา:

<link rel="stylesheet" type="text/css" href="meu.css?v=<?=hash_file('md5', $file);?>">

อ๊ะ! สิ่งนี้จะแย่มากสำหรับประสิทธิภาพและความสามารถในการปรับขนาดในการโหลดไฟล์ CSS / JS ทั้งหมดของคุณในเธรดหลักเพื่อตรวจสอบขนาด / แฮช
Dalin

@Dalin ก่อนที่คุณจะร้องไห้น้ำตาของ Gentoo ricer (ลินุกซ์ดิสเพลย์ที่รู้จักกันในชื่อ "ไปอย่างรวดเร็ว" โดยรวบรวมมากเกินไปจากแหล่งที่มาและปรับแต่งสถาปัตยกรรม) ฉันจะนาฬิกาstatโทร ไม่มีแคชระบบไฟล์ 16ns ท็อปส์ซู? ด้วยแคชเชื่อถือได้ <8ns นาโนวินาที และบนระบบของฉัน MD5 สามารถประมวลผล 754 MiB / s โดยไม่กะพริบ ( openssl speed md5) เมื่อรวมไฟล์ CSS ขนาด 100KB จะมีค่าโสหุ้ยเพิ่มเติมรวมกันเป็น… 129µs (ไมโครวินาที, 0.1295ms) + 8ns (ซึ่งไม่ได้มีส่วนช่วยในจำนวนสุดท้าย) = 129µs
amcgregor

เมื่อพิจารณาต่อไปมันทำให้ฉันเข้าใจว่าคำตอบที่ "ถูกต้อง" เพียงคำเดียว (ที่มีภาระการบำรุงรักษาต่ำที่สุดพฤติกรรมที่ถูกต้อง / น่าเชื่อถือที่สุด) เป็นทั้งคนที่ได้รับการโหวตน้อยที่สุดและถูกปฏิเสธในความคิดเห็นเดียวเกี่ยวกับเหตุผลที่บอบบางและไม่สมจริงดังกล่าว
amcgregor

คุณและฉันอาจทำงานในเว็บไซต์ที่แตกต่างกัน แต่ฉันยืนตามความคิดเห็นของฉัน หากมีเธรดพร้อมกันหลายสิบชุดที่แสดงหน้าเว็บเมื่อใดก็ได้ฉันคิดว่ามีตัวเลือกที่ดีกว่าที่คุณไม่จำเป็นต้องถามว่าสามารถปรับขนาดได้หรือไม่ hash_file('md5', $deployment_counter)หรือhash_file('md5', $cache_clear_counter)เป็นสิ่งแรกที่อยู่ในใจ
Dalin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.