Как предотвратить кеширование браузера для php-сайта

У меня есть php-сайт, работающий на облачном сервере. Когда я добавляю новые файлы css, js или изображения, браузер загружает те же старые файлы js, css и изображений, хранящиеся в кеше.

На моем сайте есть doctype и метатег, как показано ниже.

<!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)">

Из-за приведенного выше типа документа и метакода я загружаю те же файлы, кешированные в браузере, вместо новых


person ArrayOutOfBound    schedule 30.11.2012    source источник
comment
No Cache in all Browsers. Вы также можете сделать? RandomGeneratedNumber для файлов, которые не хотите кэшировать.   -  person Kodemon    schedule 30.11.2012
comment
Вероятно, вы не хотите полностью отключать кеш для изображений / js / css: stackoverflow.com/questions/4206224/   -  person FoolishSeth    schedule 30.11.2012
comment
Сопротивлялся искушению некро, но, пожалуйста, всем, кто задумывается над этим: остановитесь. Научитесь контролировать и использовать кеширование, а не просто отключать его вслепую из-за одного неудобного эпизода. Прочтите главу о кэшировании в Полном руководстве по HTTP - эту книгу (и RFC) следует прочитать в обязательном порядке с тестом. Узнайте, как указать Last-Modified, ответить на If-Modified-Since и использовать идентификацию ETag. Затем, когда актив будет обновлен, браузеры будут проинформированы, когда 304 снова станет 200.   -  person amcgregor    schedule 26.06.2020
comment
неудобный эпизод в 99.999999999999999999999999999% запросов.   -  person marioquartz    schedule 27.12.2020


Ответы (6)


попробуй это

<?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");
?>
person Codesen    schedule 30.11.2012
comment
За исключением max-age = 0, это заголовки, отправленные PHP без указания вышеуказанного в моей установке. Кажется, PHP пытается предотвратить кеширование браузера по умолчанию ... - person fast-reflexes; 19.05.2013
comment
У меня есть плагин WordPress, который отправляет альтернативную тему в старые версии Internet Explorer, и он сильно зависал в некоторых системах кеширования. Это сообщение появилось при моем первом поиске в Google. Отлично сработано. - person Imperative; 01.05.2014
comment
Имейте в виду, что это не может быть встроено в html; это должно быть в самом верху страницы. - person Hunter S; 08.11.2015
comment
anyexample.com/programming/php/ - person Virgili Garcia; 13.11.2015
comment
Это сработало, но когда я попытался использовать метатег, этого не произошло. - person Immutable Brick; 03.05.2016
comment
По какой причине вы не можете объединить первые две строчки? `заголовок (Cache-Control: no-store, no-cache, must-revalidate, max-age = 0, post-check = 0, pre-check = 0); ' - person suncat100; 12.06.2017
comment
Примечание. Если вы впоследствии используете session_start(), он перезапишет ваш заголовок на Cache-Control: private, max-age=10800, pre-check=10800, потому что 180 минут - это значение по умолчанию для session.cache_expire. Если вы не можете избежать запуска сеанса, но вам нужно отключить кеш, используйте session_cache_limiter('private');session_cache_expire(0);. - person mgutt; 03.11.2017
comment
@mgutt, это не так однозначно. Значение session.cache_limiter обычно устанавливается в php.ini. В большинстве дистрибутивов это значение по умолчанию - nocache, возвращая HTTP-заголовки, подобные этим Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache - person wp78de; 14.05.2018
comment
false требуется? - person thdoan; 26.07.2018
comment
@thdoan Второй параметр функции header является логическим вместо заменить. Необязательный параметр replace указывает, должен ли заголовок заменить предыдущий аналогичный заголовок или добавить второй заголовок того же типа. - person mrReiha; 08.12.2019

Здесь, если вы хотите управлять им через 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 ВСЕГДА ЛУЧШЕ, чтобы избежать проблем с кешированием на основе прокси.

person Ritesh Aryal    schedule 06.02.2014

Вы можете попробовать это:

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

Надеюсь, это поможет предотвратить кеширование, если таковое имеется!

person Aakanksha    schedule 27.01.2015
comment
Это относится только к кешированию файлов HTML, верно? И никакого отношения к eTag не имеет? Спасибо! - person Sam Levin; 01.05.2015
comment
просто первой строки должно хватить. Пятая строка на самом деле неверна и не имеет ничего общего с ответом сервера (это заголовок запроса). шестая строка не будет иметь никакого эффекта. я мог бы продолжить ... - person The Surrican; 26.10.2015
comment
Подход с дробовиком: бросьте все в стену, надеюсь, что что-то прилипнет. Согласно моему комментарию к самому вопросу, я настоятельно рекомендую взять копию HTTP: Полное руководство и прочтите главу о кэшировании. Также RFC, но их чтение - это особый навык. (Connection: close - это забавный шаг, который нужно включить, отключив эффективную конвейерную обработку запросов, или ничего не будет делать, но я подозреваю, что PHP действительно может это пропустить.) - person amcgregor; 26.06.2020

У меня возникла проблема с кешированием моих файлов 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(); ?>">
person Lukas    schedule 12.10.2015
comment
Произвольные версии, текущие отметки времени (полностью исключающие кеширование)… но это не единственное, что действительно имеет смысл и работает, независимо от флага отладки или нет. Почему вы не используете фактическое время файла? Тогда вам буквально никогда не понадобится обновлять PHP, и кеши не станут полностью и фантастически бесполезными. Или просто предоставьте свою статику с правильно настроенным HTTP-сервером, таким как Nginx или Apache, который устанавливает правильные Last-Modified и ETag. Точно так же этот тип флага отладки уже существует… в браузере. (Отключить кеши, обновить без кеширования, пустые кеши,…) - person amcgregor; 26.06.2020

Предотвращение кеширования браузера - не лучшая идея в зависимости от ситуации. В поисках решения я нашел такие решения:

<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);?>">
person ismavolk    schedule 21.06.2018
comment
Ой! Было бы ужасно для производительности и масштабируемости всегда загружать все ваши файлы CSS / JS в основном потоке, чтобы проверить их размер / хэш. - person Dalin; 05.03.2020
comment
@Dalin Прежде чем вы заплачете в слезы Gentoo ricer (дистрибутив Linux, известный своей быстротой из-за чрезмерной компиляции из исходных кодов и настройки архитектуры), я бы засек stat звонок. Без кеша файловой системы, 16нс, вершины? С кешем надежно ‹8нс. Наносекунды. А в моей системе MD5 может обрабатывать 754 МБ / с без мигания. (openssl speed md5) В совокупности файл CSS размером 100 КБ будет иметь комбинированные дополнительные накладные расходы в размере… 129 мкс (микросекунд, 0,1295 мс) + 8 нс (что не влияет на окончательное число) = 129 мкс. - person amcgregor; 26.06.2020
comment
При дальнейшем рассмотрении меня поражает, что единственный правильный ответ (с наименьшими затратами на обслуживание, наиболее точным / надежным поведением) является как наименее проголосованным, так и отклоненным в одном комментарии по таким надуманным и нереалистичным основаниям. - person amcgregor; 26.06.2020
comment
Мы с вами, наверное, работаем на разных сайтах. Но я придерживаюсь своего комментария. Если есть десятки параллельных потоков, доставляющих веб-страницы в любой момент времени, тогда, я думаю, есть лучшие варианты, и вам даже не придется сомневаться в том, масштабируем ли они. hash_file('md5', $deployment_counter) или hash_file('md5', $cache_clear_counter) - это первое, что приходит на ум. - person Dalin; 29.06.2020
comment
@Dalin Итак ... потоковая передача всего файла с диска (в конечном итоге кеш VFS ядра) для повторного хеширования при каждом доступе? Даже если время mtime не изменилось? До того, как в это решение будет добавлен хеш-кеш… только уйти от стандартных механизмов кэширования HTTP. Я знаю, что упоминал о хешировании, но это абсолютно чрезмерно. Обратитесь к §7 (Кэширование), а для конкретных деталей обратитесь к §1.8.2, §3.5.1.1, §3.5.4.2, §13.4.5, §17.4.1 и с §20.6 по §20.10 из HTTP: полное руководство. Это замечательно хорошая ссылка. - person amcgregor; 22.08.2020

Вы также можете использовать строку запроса для ваших кэшированных файлов. Это не повлияет ни на поведение вашего стиля, ни на js-файлы.

Например:

example.com/mystyle.css -> 
example.com/mystyle.css?<?php echo random(1000, 5000); ?>
person Emre Pişirici    schedule 02.03.2021