borrame.com - Colección particular de recortes de código y documentación para programación web

Canales RSS

Lo más fresco

  1. Vaciar un esquema de Oracle Nuevo
  2. Conectarse a MySQL con PDO Nuevo
  3. Reiniciar secuencia en Oracle Modificado
  4. Fechas automáticas en Oracle Modificado
  5. Campo autonumérico en Oracle Modificado
  6. Dígito de control de una cuenta bancaria Modificado

Sugerencias del chef

Lo más visitado

  1. Dar formato a un número
  2. Fecha y hora
  3. Rotar logs en Windows
  4. Reiniciar secuencia
  5. Campo autonumérico
Compartir esta página

Caché del navegador

Guardar en caché

A menudo se emplea PHP simplemente para añadir menús, encabezados o pies de página usando el tradicional include(). Un efecto secundario es que al tratarse de un script en PHP la página ya no se guarda en la caché del navegador y se descarga desde Internet cada vez que se visualiza; sieeeempre la misma página porque nada cambia en ella de una vez a otra.

Con esta función, llamada al principio de nuestro script, le indicamos al navegador la fecha real de la última modificación y cuánto tiempo debe conservar la página en caché.

/**
 * Genera los encabezados necesarios para indicar que el documento se guarde o no en caché
 *
 * $activar (bool): genera encabezados para guardar en caché (TRUE) o para no cachear (FALSE)
 * $horas (entero): tiempo que el navegador debe conservar la página en caché
 * $if_modified_since (bool): indica si respetar el encabezado If-Modified-Since
 *
 * Si $if_modified_since es TRUE, cuando la página no se ha modificado desde la fecha indicada en
 * If-Modified-Since se genera un código de estado HTTP 304 y se detiene la ejecución del script
 *
 * Nota: esta función utiliza la fecha de modificación de la _página actual_ como referencia. Esta fecha
 * no tiene en cuenta otros archivos (como bloques situados en includes) o contenidos dinámicos por lo que
 * sólo es una medida fiable en páginas estáticas o pseudo-estáticas. Esto es un problema si se utiliza
 * $if_modified_since=TRUE en páginas dinámicas ya que el navedor podría conservar una versión obsoleta
 * mucho más allá de lo establecido en $horas
 */

function cache($activar, $horas=3, $if_modified_since=FALSE){ //v2011-02-11
    // Obecedemos If-Modified-Since si queremos usar caché
    if( $activar && $if_modified_since && isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ){
        $fecha_cache = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
        if( $fecha_cache!==FALSE && $fecha_cache>=getlastmod() ){
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s', getlastmod()) . ' GMT', TRUE, 304);
            exit;
        }
    }

    header('Last-Modified: ' . gmdate('D, d M Y H:i:s', getlastmod()) . ' GMT');

    if($activar){
        // Guardar en caché
        header('Expires: ' . gmdate('D, d M Y H:i:s', time()+60*60*$horas) . ' GMT');
        header('Cache-Control: max-age=' . 60*60*$horas . ', s-maxage=' . 60*60*$horas . ', must-revalidate, proxy-revalidate');

        session_cache_limiter(FALSE); // Deshabilitamos los encabezados de caché de session_start()
        if( session_id() ){
            // Una sesión ya iniciada ha generado un encabezado Pragma: no-cache
            if( function_exists('header_remove') ){
                header_remove('Pragma');
            }else{
                header('Pragma:');
            }
        }

    }else{
        // No guardar en caché
        header('Expires: ' . gmdate('D, d M Y H:i:s', time()-86400*365*10) . ' GMT');
        header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
        header('Pragma: no-cache');
    }
}

Nótese que esto no nos impide recargar la página con el botón de actualizar y, en cambio, hace mucho más ágil navegar por el sitio.

No guardar en caché

Si no queremos reutilizar la página de la caché podemos llamar a la función con $activar=FALSE. O podemos simplemente no llamarla: ésa acostumbra a ser configuración predeterminada de PHP.

Notas

Acerca de If-Modified-Since

Este encabezado HTTP, enviado por el navegador, permite mantener una conversación tal que así:

Al contrario que con el sistema «ten esto tres horitas en caché y luego me lo vuelves a pedir», el navegador conservará la versión que tenga hasta que le digamos que la página ha cambiado. Y si la página cambia sin que nos demos cuenta esto pueden ser semanas o meses. Para que el sistema sea funcional necesitamos bien que la página sea estática (en cuyo caso getlastmod() nos da la información correcta) bien indicar a mano la fecha de modificación (sería fácil retocar la función para alimentarla con una fecha sacada de, por ejemplo, la base de datos). Si no se está seguro es mejor dejar $if_modified_since=FALSE.

Historial

v2011-02-11
Documentar mejor los parámetros y cambiar el valor predeterminado de $if_modified_since.
v2010-08-23
Implementar la respuesta al encabezado If-Modified-Since.
La caché no se activaba en páginas con sesiones si la sesión había sido iniciada con anterioridad.
Generar el encabezado Last-Modified también al desactivar la caché.
v2009-05-08
Agrupado el código en una función y actualizadas las explicaciones.
La caché no se activaba en páginas con sesiones.
v2005-08-25
Primera versión.

Esta página ha sido impresa el viernes 24 de mayo de 2013 (11:24:01 +0200) desde http://borrame.com/recortes/php/cache-navegador.html. La última vez que miré contenía HTML válido con CSS fresquito y si tiene flatas de ortografía ha sido sin querer.

borrame.com es el sitio anteriormente conocido como bits.demogracia.com (no confundir con Demogracia, que sólo pasaba por ahí).

© 2005-2013 by Álvaro G. Vicario (alvaro.es) • Burgos (España) • borrame.com