68 votes

Comment utiliser les en-têtes de cache HTTP avec PHP

J'ai un PHP 5.1.0 site web (en fait, c'est 5.2.9 mais il doit également s'exécuter sur 5.1.0+).

Les Pages sont générées dynamiquement, mais beaucoup d'entre eux sont principalement statique. En statique, je veux dire le contenu ne change pas, mais le "modèle" autour du contenu peut changer au fil du temps.

Je sais qu'ils sont plusieurs systèmes de cache et des frameworks PHP déjà là, mais mon hôte n'ont pas d'APC ou Memcached installé et je n'utilise pas de framework pour ce projet particulier.

Je veux que les pages mises en cache (je pense que par défaut PHP "interdire" cache). Jusqu'à présent, je suis en utilisant:

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

J'ai lu plusieurs tutoriels mais je ne peux pas trouver quelque chose de simple (je sais cache est quelque chose de complexe, mais j'ai seulement besoin de quelques trucs de base).

Que sont les "doivent" avoir des en-têtes à envoyer pour aider à la mise en cache?

Merci!

52voto

Steve-o Points 9043

Vous voudrez peut-être utiliser private_no_expire au lieu de private , mais définissez une expiration longue pour le contenu que vous savez ne va pas changer et assurez-vous de traiter if-modified-since et if-none-match demandes similaires au message de Emil.

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

$etag pourrait être une somme de contrôle basée sur le contenu ou l'ID utilisateur, la langue et l'horodatage, par exemple

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

13voto

Emil Vikström Points 42251

Vous devez avoir un en-tête Expires. Techniquement, il y a d'autres solutions, mais l'en-tête Expires est vraiment le meilleur, parce qu'il indique au navigateur de ne pas vérifier de nouveau la page, avant l'expiration de la date et de l'heure et servez-le tout simplement le contenu de la mémoire cache. Il fonctionne vraiment très bien!

Il est également utile de vérifier pour un Si-Modified-since en-tête de la requête à partir du navigateur. Cet en-tête est envoyée lorsque le navigateur est "pas sûr" si le contenu du cache est toujours la bonne version. Si votre page n'est pas modifiée depuis ce temps, il suffit de renvoyer un HTTP code 304 (Non Modifiée). Voici un exemple qui fonctionne sur un serveur Apache et envoie un code 304 dix minutes:

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

Vous pouvez mettre cette case au début de votre code pour économiser les ressources du serveur.

9voto

Mike Foster Points 155

Faites votre choix - ou utilisez-les tous! :-)

en-tête ('Expire: jeu., 01-janv.-70 00:00:01 GMT');
en-tête ('Last-Modified:'. gmdate ('D, d MYH: i: s'). 'GMT');
en-tête ('Cache-Control: no-store, no-cache, must-revalidate');
en-tête ('Cache-Control: post-check = 0, pré-check = 0', false);
en-tête ('Pragma: no-cache');

8voto

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

Définir une date d'expiration pour la page mise en cache est un moyen utile de la mettre en cache côté client.

8voto

Jasper Points 299

Voici une petite classe qui met en cache HTTP pour vous. Il a une fonction statique appelée 'Init' qui nécessite 2 paramètres, un horodatage de la date de dernière modification de la page (ou de tout autre fichier demandé par le navigateur) et l'âge maximum, en secondes, dans lequel cette page peut être conservée. cache par le navigateur.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X