Comment empêcher le cache du navigateur pour le site PHP

121

J'ai un site php en cours d'exécution sur un serveur cloud. Quand j'ajoute de nouveaux fichiers css, js ou images, le navigateur charge les mêmes anciens fichiers js, css et image stockés dans le cache.

Mon site a un doctype et une balise meta comme ci-dessous

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

En raison du doctype et du méta-code ci-dessus, je charge les mêmes fichiers mis en cache dans le navigateur au lieu d'un nouveau

ArrayOutOfBound
la source
No Cache in all Browsers. Vous pouvez également faire un? RandomGeneratedNumber sur les fichiers que vous ne souhaitez pas mettre en cache.
Kodemon
2
Vous ne voulez probablement pas désactiver complètement le cache pour images / js / css: stackoverflow.com/questions/4206224/…
FoolishSeth
Résisté à la tentation de nécro, mais s'il vous plaît, quiconque envisage ceci: arrêtez. Apprenez à contrôler et à utiliser la mise en cache, ne la désactivez pas aveuglément à cause d'un épisode gênant. Lisez le chapitre sur la mise en cache à partir de HTTP The Definitive Guide - ce livre (et les RFC) devrait être une lecture obligatoire, avec un test. Apprenez à spécifier le Last-Modified, à répondre à If-Modified-Since et à utiliser l'identification ETag. Ensuite, lorsque l'actif est mis à jour, les navigateurs seront informés lorsque ce 304 redevient un 200.
amcgregor le

Réponses:

283

essaye ça

<?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");
?>
Codesen
la source
6
Sauf pour "max-age = 0", ce sont les en-têtes envoyés par PHP sans spécifier ce qui précède dans mon installation .. Il semble que PHP essaie d'empêcher la mise en cache du navigateur par défaut ...
fast-reflexes
1
J'ai un plugin WordPress qui envoie un thème alternatif aux anciennes versions d'Internet Explorer et il commençait à mal tourner sur certains systèmes de mise en cache. Ce message a été publié lors de ma première recherche Google. Bien joué.
Impératif
3
Gardez à l'esprit que cela ne peut pas être intégré à l'intérieur de html; cela devrait être tout en haut de la page.
Hunter S
9
Remarque: Si vous utilisez session_start()après, il remplacera votre en-tête Cache-Control: private, max-age=10800, pre-check=10800car 180 minutes est la valeur par défaut de session.cache_expire. Si vous ne pouvez pas éviter de démarrer la session, mais que vous devez désactiver l'utilisation du cache session_cache_limiter('private');session_cache_expire(0);.
mgutt
2
@thdoan Le deuxième paramètre de headerfunction est un booléen pour replace . Le paramètre de remplacement facultatif indique si l'en-tête doit remplacer un en-tête similaire précédent ou ajouter un deuxième en-tête du même type.
mrReiha
36

Ici, si vous voulez le contrôler via HTML: faites comme ci-dessous Option 1:

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

Et si vous voulez le contrôler via PHP: faites-le comme ci-dessous Option 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');

ET l' option 2 EST TOUJOURS MIEUX afin d'éviter les problèmes de mise en cache basée sur un proxy.

Ritesh Aryal
la source
10

Vous pouvez essayer ceci:

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

Espérons que cela aidera à empêcher le cache, le cas échéant!

Aakanksha
la source
Cela ne concerne que la mise en cache des fichiers HTML, n'est-ce pas? Et n'a rien à voir avec eTag? Merci!
Sam Levin
4
seule la première ligne devrait parfaitement suffire. La 5ème ligne est en fait complètement fausse et n'a rien à voir dans une réponse du serveur (c'est un en-tête de requête). la sixième ligne n'aura aucun effet. Je pourrais continuer ...
The Surrican
L'approche du fusil de chasse: jetez tout sur le mur, espérez que quelque chose colle. Selon mon commentaire sur la question elle-même, je peux fortement recommander de récupérer une copie de HTTP: The Definitive Guide et de lire le chapitre sur la mise en cache. Aussi les RFC, mais leur lecture est une compétence distincte. ("Connection: close" est un foot-shot hilarant à inclure, désactivant le pipelining efficace des requêtes, ou ne fera rien, mais je soupçonne que PHP pourrait réellement laisser passer cela.)
amcgregor
7

J'ai eu un problème avec la mise en cache de mes fichiers css. Définir des en-têtes en PHP ne m'a pas aidé (peut-être parce que les en-têtes devraient être définis dans le fichier de feuille de style au lieu de la page qui y est liée?).

J'ai trouvé la solution sur cette page: https://css-tricks.com/can-we-prevent-css-caching/

La solution:

Ajoutez l'horodatage en tant que partie requête de l'URI du fichier lié.
(Peut être utilisé pour css, js, images, etc.)

Pour le developpement:

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

Pour la production (où la mise en cache est surtout une bonne chose):

<link rel="stylesheet" type="text/css" href="style.css?version=3.2">
(et réécrire manuellement si nécessaire)

Ou combinaison de ces deux:

<?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') : ""; ?>">

ÉDITER:

Ou une plus jolie combinaison de ces deux:

<?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(); ?>">
Lukas
la source
Versions arbitraires, horodatages actuels (vaincre complètement la mise en cache)… mais pas la seule chose qui a vraiment du sens et qui fonctionne, indépendamment d'un indicateur de «débogage» ou non. Pourquoi n'utilisez-vous pas le mtime réel du fichier? Ensuite, vous n'aurez littéralement jamais besoin de mettre à jour PHP, et les caches ne deviendraient pas complètement et fantastiquement inutiles. Ou fournissez simplement vos statistiques avec un serveur HTTP correctement configuré comme Nginx ou Apache qui définit un Last-Modified et un ETag appropriés. De même, ce type d'indicateur de "débogage" existe déjà… dans le navigateur. (Désactiver les caches, actualiser sans cache, vider les caches,…)
amcgregor
5

Empêcher le cache du navigateur n'est pas une bonne idée selon le cas. À la recherche d'une solution, j'ai trouvé des solutions comme celle-ci:

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

le problème ici est que si le fichier est écrasé lors d'une mise à jour sur le serveur, ce qui est mon scénario, le cache est ignoré car l'horodatage est modifié même le contenu du fichier est le même.

J'utilise cette solution pour forcer le navigateur à télécharger des actifs uniquement si son contenu est modifié:

<link rel="stylesheet" type="text/css" href="meu.css?v=<?=hash_file('md5', $file);?>">
Ismavolk
la source
Yikes! Ce serait terrible pour les performances et l'évolutivité de toujours charger tous vos fichiers CSS / JS dans le thread principal pour vérifier leur taille / hachage.
Dalin
@Dalin Avant de pleurer les larmes de Gentoo ricer (une distribution Linux connue pour "aller vite" en étant excessivement compilée à partir de la source et réglée sur l'architecture) je chronométrerais un statappel. Sans cache du système de fichiers, 16ns, tops? Avec cache, de manière fiable <8ns. Nanosecondes. Et sur mon système, MD5 peut traiter 754 Mio / s sans clignoter. ( openssl speed md5) Combiné, un fichier CSS de 100 Ko aurait une surcharge supplémentaire combinée de… 129 µs (microsecondes, 0,1295 ms) + 8 ns (ce qui ne contribue pas de manière significative au nombre final) = 129 µs.
amcgregor le
Après un examen plus approfondi, je suis époustouflé par le fait que la seule réponse «correcte» (avec le plus faible fardeau de maintenance, le comportement le plus précis / fiable) est à la fois la moins votée et rejetée en un seul commentaire sur des motifs aussi fragiles et irréalistes.
amcgregor le
Vous et moi travaillons probablement sur différents sites Web. Mais je maintiens mon commentaire. S'il y a des dizaines de threads simultanés fournissant des pages Web à tout moment, je pense qu'il existe de meilleures options dont vous n'aurez même pas besoin de vous demander si elles sont évolutives. hash_file('md5', $deployment_counter)ou hash_file('md5', $cache_clear_counter)sont les premiers qui viennent à l'esprit.
Dalin le