Come configurare smartphone e PC. Portale informativo
  • casa
  • Programmi
  • Memorizzazione nella cache in PHP. Metodi per memorizzare nella cache i dati in PHP

Memorizzazione nella cache in PHP. Metodi per memorizzare nella cache i dati in PHP


memorizzazione nella cache in PHP

Ai vecchi tempi, quando creare siti Web era semplice come digitare alcune pagine HTML, inviare pagine Web al browser era semplicemente una questione di invio di un file da parte del server Web. I visitatori del sito potevano vedere queste piccole pagine di solo testo quasi istantaneamente (ad eccezione degli utenti di modem lenti). Una volta caricata la pagina, il browser la memorizza nella cache da qualche parte sul computer locale in modo che, se la pagina viene richiesta nuovamente, possa recuperare la versione locale dalla cache, inviando solo una breve richiesta per garantire che la pagina sul server non sia stata caricata. stato modificato. Le richieste sono state elaborate in modo rapido ed efficiente e tutti erano contenti (tranne quelli che utilizzavano modem a 9600 baud).

L'avvento delle pagine web dinamiche ha cambiato le cose in peggio, interrompendo di fatto questo modello di servizio delle pagine web a causa di due problemi:

1. Quando il server riceve una richiesta per una pagina Web dinamica, vengono eseguite alcune elaborazioni intermedie, ad esempio l'analisi dello script da parte del motore PHP, che deve essere completata. Questo ci dà un ritardo prima che il server web inizi a inviare l'output al browser. Per un semplice script PHP questo non è significativo, ma nel caso di un'applicazione più complessa il motore PHP può eseguire molte azioni prima che la pagina sia pronta per essere inviata. Questi passaggi aggiuntivi comportano un notevole ritardo tra le richieste degli utenti e le pagine effettivamente visualizzate nei loro browser.

2. Un tipico server web, come Apache, utilizza il tempo di modifica del file per comunicare correttamente al browser lo stato della cache della pagina richiesta. Nei siti Web dinamici, lo script PHP stesso può cambiare solo occasionalmente, mentre il contenuto visualizzato, eventualmente residente in un database, cambia frequentemente. Il server web non ha modo di conoscere le modifiche al database, quindi non invia la data dell'ultima modifica. Se il client (browser) non riceve alcuna indicazione su quanto tempo i dati sono corretti, presuppone che la prossima volta dovrà richiedere una nuova pagina. Il server web risponderà sempre con una versione aggiornata della pagina, indipendentemente dal fatto che i dati siano cambiati. Per evitare questo inconveniente, la maggior parte degli sviluppatori web utilizza meta tag o intestazioni HTTP per indicare al browser di non utilizzare mai la versione memorizzata nella cache della pagina. Tuttavia, ciò annulla la naturale capacità del browser Web di memorizzare nella cache le pagine Web e presenta alcuni svantaggi significativi. Ad esempio, il contenuto di una pagina dinamica può cambiare una volta al giorno, quindi il vantaggio ottenuto dal fatto che il browser memorizzi la pagina nella cache anche per 24 ore è evidente.

Di solito per le piccole applicazioni PHP è del tutto possibile ignorare l'esistenza di questi problemi, ma con l'aumento della complessità e del traffico del tuo sito, potresti riscontrare problemi. Entrambi questi problemi possono però essere risolti: il primo tramite il caching lato server, il secondo gestendo il caching lato client dalla propria applicazione. L'approccio che adotterai dipenderà dalle tue esigenze specifiche, ma in questo articolo mostreremo come risolvere entrambi i problemi utilizzando PHP e alcune classi della libreria PEAR.

come posso impedire ai browser di memorizzare nella cache una pagina?

Prima di esaminare le tecniche di memorizzazione nella cache del client e del server, dobbiamo innanzitutto capire come impedire al browser Web (e ai server proxy) di memorizzare nella cache le pagine. Il modo principale per raggiungere questo obiettivo è utilizzare i meta tag HTML:

Inserendo una data passata nel meta tag Expires, indichi al browser che la copia cache della pagina è sempre obsoleta. Ciò significa che il browser non dovrebbe mai memorizzare la pagina nella cache. Meta tag Pragma: no-cache è una convenzione abbastanza ben supportata seguita dalla maggior parte dei browser web. Una volta rilevato questo tag, di solito non memorizzano la pagina nella cache (anche se non esiste alcuna garanzia, questa è solo una convenzione). Sembra una buona cosa, ma ci sono due problemi con l'utilizzo dei meta tag:

1. Se il tag non esisteva quando la pagina è stata richiesta per la prima volta dal browser, ma appare successivamente (ad esempio, hai modificato il file include pageheader.php che è l'intestazione di ogni pagina web), il browser rimarrà beatamente inconsapevole e utilizzare la copia cache dell'originale.

2. I server proxy che memorizzano nella cache le pagine Web non esamineranno affatto direttamente il contenuto del documento HTML. Si affidano invece solo al server web da cui provengono i documenti e al protocollo HTTP. In altre parole, il browser potrebbe pensare che non dovrebbe memorizzare nella cache la pagina, ma il proxy tra il browser e il server web probabilmente non lo sa e continuerà a inviare la stessa pagina al client.

Un approccio migliore è utilizzare il protocollo HTTP direttamente utilizzando la funzione di intestazione PHP:


header("Pragma: no-cache");
?>

Possiamo fare un ulteriore passo avanti utilizzando l'intestazione Cache-Control, che è compatibile con i browser che supportano HTTP 1.1:

header("Scadenza: lunedì 26 luglio 1997 05: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");
?>

Ciò garantisce che nessun browser Web o server proxy intermedio memorizzi la pagina nella cache, quindi i visitatori ricevono sempre la versione più aggiornata del contenuto. In effetti, la prima intestazione dovrebbe essere autonoma; questo è il modo migliore per garantire che la pagina non venga memorizzata nella cache. Le intestazioni Cache-Control e Pragma vengono aggiunte per motivi di sicurezza. Anche se non funzionano con tutti i browser o proxy, rilevano alcuni casi in cui Expires non funziona come previsto (ad esempio, se la data sul computer del cliente è impostata in modo errato). Naturalmente, evitare del tutto la memorizzazione nella cache ci pone di fronte ai problemi di cui abbiamo discusso all'inizio di questo capitolo. Vedremo ora come risolvere questi problemi.

Internet Explorer e memorizzazione nella cache dei download di file

Possono sorgere problemi quando si ha a che fare con la memorizzazione nella cache e il download di file. Se, quando si esegue il download di un file tramite uno script PHP, vengono utilizzate intestazioni come Content-Disposition: attach, filename=myFile.pdf o Content-Disposition: inline, filename=myFile.pdf, si avranno problemi con Internet Explorer se si dire al browser di non memorizzare nella cache la pagina.

Internet Explorer gestisce i download in un modo piuttosto insolito, effettuando due richieste al sito web. La prima richiesta scarica il file e lo memorizza nella cache finché non viene effettuata la seconda richiesta (senza memorizzare la risposta). Questa richiesta fa sì che il file venga trasferito all'utente finale in base al tipo di file (ad esempio, avvia Acrobat Reader se il file è un documento PDF). Ciò significa che se invii intestazioni che impediscono al browser di memorizzare nella cache la pagina, Internet Explorer eliminerà il file tra la prima e la seconda richiesta, senza risultato per l'utente finale. Se il file che stai utilizzando come script PHP non cambia, una delle soluzioni più semplici è rimuovere le intestazioni di "inibizione della cache" dallo script.

Se il file scaricato cambia regolarmente (ovvero, desideri che il browser scarichi la versione più recente), dovresti utilizzare l'intestazione Last-Modified e assicurarti che il tempo di modifica tra due richieste consecutive non cambi. È necessario farlo in modo da non influire sugli utenti dei browser che gestiscono correttamente i download. Una soluzione in questo caso sarebbe quella di archiviare il file sul tuo server web e fornire un semplice collegamento ad esso, consentendo al server web di segnalare le intestazioni della cache per te. Naturalmente questa soluzione potrebbe non essere accettabile se si presuppone l'accesso autorizzato al file, poiché consente il caricamento diretto del file archiviato.

come posso acquisire i dati lato server per la memorizzazione nella cache?

È tempo di vedere come possiamo ridurre la latenza utilizzando la memorizzazione nella cache dell'output lato server. Quindi, puoi servire la pagina come al solito, eseguendo query sul database e così via in PHP. Ma prima di inviare il risultato al browser, lo acquisiamo e salviamo la pagina finita, ad esempio, in un file. Alla richiesta successiva, lo script PHP verifica innanzitutto la presenza di una versione della pagina memorizzata nella cache. Se esiste, lo script invia la versione memorizzata nella cache al browser, eliminando così il ritardo nella ricreazione della pagina.

Qualche parola sulla memorizzazione nella cache utilizzando i modelli. La presenza di motori di template come Smarty parla spesso di memorizzazione nella cache dei template. In genere, questi motori offrono un meccanismo integrato per salvare una versione compilata del modello (ovvero, generare codice sorgente PHP dal modello), che ci evita di dover analizzare il modello ogni volta che viene richiesta una pagina. Questo non deve essere confuso con il caching dell'output, che si riferisce alla memorizzazione nella cache dell'HTML fornito (o di altro output) che PHP invia al browser. Puoi utilizzare con successo entrambi i tipi di memorizzazione nella cache contemporaneamente sullo stesso sito.

Vedremo ora il meccanismo di memorizzazione nella cache integrato di PHP che utilizza il buffering dell'output, che puoi utilizzare indipendentemente da come crei il tuo contenuto (con o senza modelli). Considera una situazione in cui il tuo script visualizza il risultato, utilizzando, ad esempio, echo o print per inviare i dati direttamente al browser. In tal caso, puoi utilizzare le funzioni di controllo dell'output di PHP per archiviare i dati nella memoria buffer su cui lo script PHP ha il controllo.
Ecco un semplice esempio:


ob_inizio();
// Emette del testo (che viene salvato nel buffer);
echo "1. Invialo al buffer
";
// Ottiene il contenuto del buffer
$buffer = ob_get_contents();
// Interrompe il buffering e cancella il buffer di output
ob_end_clean();
// Emette del testo come al solito
echo "2. Uscita normale
";
// Stampa il contenuto del buffer
echo $buffer;
?>

Il buffer stesso memorizza l'output come una stringa. Quindi, nello script sopra, iniziamo il buffering con ob_start e usiamo echo per produrre qualcosa. Utilizziamo quindi ob_get_contents per recuperare i dati memorizzati nel buffer dall'echo istruzione e memorizzarli in una stringa. La funzione ob_end_clean interrompe il buffering dell'output e ne distrugge il contenuto. In alternativa, puoi usare ob_end_flush per stampare il contenuto del buffer. Lo script sopra restituirà:

2. Uscita normale
1. Invialo al buffer

In altre parole, abbiamo catturato l'output del primo eco, quindi lo abbiamo inviato al browser dopo il secondo eco. Come puoi vedere da questo semplice esempio, il buffering dell'output è uno strumento molto potente per modellare il tuo sito, fornisce una soluzione di memorizzazione nella cache come vedremo a breve ed è un ottimo modo per nascondere gli errori ai visitatori del tuo sito. Fornisce inoltre un'opzione alternativa per il reindirizzamento del browser in situazioni come l'autenticazione dell'utente.

Intestazioni HTTP e buffering dell'output

Il buffering dell'output può aiutare a risolvere il problema più comune con la funzione header, per non parlare di session_start e set_cookie. In genere, se chiami una di queste funzioni dopo che la pagina ha iniziato il rendering, riceverai un brutto messaggio di errore. Quando il buffering dell'output è abilitato, l'unico tipo di output che evita il buffering sono le intestazioni HTTP. Usando ob_start proprio all'inizio dell'esecuzione della tua applicazione, puoi inviare intestazioni in qualsiasi punto del programma che preferisci senza incontrare i soliti errori. Quindi, una volta che sei sicuro di non aver bisogno di stampare altre intestazioni HTTP, puoi stampare subito il contenuto della pagina dal buffer.

/* Va notato che tale utilizzo di questa funzione è ingiustificato. Nella maggior parte dei casi, semplicemente non è necessario utilizzare il buffering dell'output per eliminare errori di questo tipo e tutto può essere facilmente corretto con una corretta progettazione dell'applicazione - ca. traduttore */

utilizzando il buffering di output per la memorizzazione nella cache lato server

Hai già visto un esempio base di buffering dell'output, ora il passaggio successivo è il salvataggio del buffer in un file:

// Se esiste una versione memorizzata nella cache...
if (file_esiste("./cache/2.cache")) (
// Legge e genera il file
leggifile("./cache/2.cache");
Uscita();
}
// Avvia il buffering dell'output
ob_inizio();
// Visualizza il resto dell'HTML
?>
>http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
>http://www.w3.org/1999/xhtml">

Pagina memorizzata nella cache

Questa pagina viene memorizzata nella cache utilizzando PHP
Funzioni>http://www.php.net/outcontrol">Funzioni di controllo dell'output

// Ottiene il contenuto del buffer
$buffer = ob_get_contents();
// Interrompe il buffering e visualizza il buffer
ob_end_flush();
// Salvataggio di un file di cache con contenuto
$fp = fopen("./cache/2.cache", "w");
fwrite($fp, $buffer);
fclose($fp);
?>

Innanzitutto, questo script verifica la presenza di una versione della pagina nella cache e, se esiste, lo script la legge e la visualizza. Altrimenti, utilizza il buffering di output per creare una versione memorizzata nella cache della pagina. Dopo aver utilizzato ob_end_flush per visualizzare la pagina all'utente, questa viene salvata come file.

buffering del blocco

In un approccio semplificato, memorizziamo nella cache il buffer di output come una singola pagina. Tuttavia, questo approccio toglie la reale funzionalità fornita dalle funzioni di controllo dell'output di PHP.
Senza dubbio, alcune parti della pagina che invii al tuo visitatore cambiano molto raramente, come l'intestazione, il menu e il piè di pagina. Tuttavia, altre parti, come le tabelle contenenti le discussioni nei forum, possono cambiare con una certa frequenza. Il buffering dell'output può essere utilizzato per memorizzare nella cache sezioni di una pagina in file separati, quindi costruire la pagina da essi: una soluzione che elimina la necessità di ripetute query sul database, cicli while, ecc. È possibile assegnare a ciascun blocco di pagina una data di scadenza dopo la quale il file di cache viene ricreato o, in alternativa, è possibile includere un meccanismo nell'applicazione che eliminerà il file di cache ogni volta che il contenuto in esso archiviato viene modificato.
Ecco un esempio che dimostra questo principio:

/
* Scrivi il file della cache
* Contenuto della stringa @param – contenuto del buffer
* @param string filename – nome file utilizzato durante la creazione del file cache
* @restituzione nulla
*/
funzione writeCache($contenuto, $nomefile) (
$fp = fopen("./cache/" . $nomefile, "w");
fwrite($fp, $contenuto);
fclose($fp);
}
* Controllo dei file della cache
* @param string filename – nome del file di cache da controllare
* @param int scadenza – “età” massima del file in secondi
* @return contenuto cache misto o false
*/
funzione readCache($nomefile, $scadenza) (
if (file_esiste("./cache/" . $nomefile)) (
if ((time() - $scadenza) >filemtime("./cache/" . $nomefile))
restituisce FALSO;
$cache = file("./cache/" . $nomefile);
return implode("", $cache);
}
restituisce FALSO;
}
?>

Le prime due funzioni che abbiamo definito, writeCache e readCache, vengono utilizzate rispettivamente per creare file di cache e verificarne l'esistenza. La funzione writeCache accetta come argomenti i dati da memorizzare nella cache e il nome del file utilizzato per creare il file di cache. La funzione readCache ottiene il nome del file di cache e il tempo in secondi dopo il quale il file di cache dovrebbe essere considerato obsoleto. Se trova il file di cache valido, lo script ne restituirà il contenuto, altrimenti restituirà FALSE per indicare che il file di cache non esiste o non è aggiornato.

In questo esempio ho utilizzato un approccio procedurale. Tuttavia, non consiglio di farlo in pratica, poiché si otterrebbe un codice molto confuso (vedere le soluzioni successive per un'alternativa migliore) e probabilmente causerebbe problemi di blocco dei file (ad esempio, cosa succede quando qualcuno accede alla cache mentre viene aggiornato?).
Continuiamo con questo esempio. Una volta avviato il buffering dell'output, inizia l'elaborazione. Lo script chiama prima readCache per vedere se esiste il file 3_header.cache: contiene l'intestazione della pagina, ovvero l'intestazione HTML e l'inizio del corpo. Usiamo la funzione data per restituire l'ora in cui la pagina è stata effettivamente generata, quindi vedrai i vari file di cache in azione quando viene eseguito il rendering della pagina.

// Avvia il buffering dell'output
ob_inizio();
// Elabora l'intestazione
if (!$header = readCache("3_header.cache", 604800)) (
// Uscita dell'intestazione
?>
>http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
>http://www.w3.org/1999/xhtml">

Pagina memorizzata nella cache blocco per blocco

Orario di creazione dell'intestazione:

$intestazione = ob_get_contents();
ob_pulito();
writeCache($header,"3_header.cache");
}
?>

Cosa succede quando il file della cache non viene trovato? Parte del contenuto viene emesso e assegnato a una variabile utilizzando ob_get_contents, dopodiché il buffer viene cancellato dalla funzione ob_clean. Ciò ci consente di acquisire l'output pezzo per pezzo e abbinarlo ai singoli file di cache utilizzando writeCache. Il titolo della pagina è ora memorizzato come file che può essere utilizzato senza il nostro intervento nella ricostruzione della pagina. Torniamo per un secondo all'inizio dell'enunciato condizionale. Quando abbiamo chiamato readCache gli abbiamo passato una durata della cache di 604800 secondi (una settimana), readCache utilizza il tempo di modifica del file di cache per determinare se il file di cache è ancora valido.

Per il contenuto (corpo) della pagina utilizzeremo ancora lo stesso procedimento. Tuttavia, questa volta quando chiameremo readCache utilizzeremo una durata della cache di cinque secondi, il file della cache verrà modificato ogni volta che è “più vecchio” di 5 secondi:

// Elabora il corpo della pagina
if (!$body = readCache("3_body.cache", 5)) (
echo "Ora di creazione del corpo: " . data("H:i:s") . "
";
$corpo = ob_get_contents();
ob_pulito();
writeCache($corpo, "3_body.cache");
}
?>

Il piè di pagina può essere modificato in modo efficace allo stesso modo dell'intestazione.
Il risultato finale è simile a questo:
- ora di creazione dell'intestazione - 17:10:42;
- ora di creazione del corpo - 18:07:40;
- ora di creazione del piè di pagina - 17:10:42.
L'intestazione e il piè di pagina vengono aggiornati settimanalmente, mentre il corpo viene modificato quando è più vecchio di 5 secondi.

buffer nidificati

Puoi nidificare un buffer all'interno di un altro praticamente indefinitamente semplicemente chiamando ob_start ripetutamente. Questo può essere utile se hai molte operazioni che utilizzano il buffer di output, ad esempio alcune che rilevano messaggi di errore PHP, altre che si occupano della memorizzazione nella cache. È necessario assicurarsi che ob_end_flush o ob_end_clean venga chiamato ogni volta che viene utilizzato ob_start.

Come posso implementare un semplice sistema di caching lato server?
Ora che abbiamo compreso le idee alla base del buffering dell'output, è tempo di vedere come possiamo mettere in atto questo processo in un modo che sia facile da mantenere. Per fare ciò, utilizzeremo un piccolo aiuto da PEAR::CacheLite.

Come ho detto, nell'interesse di rendere il codice più facile da mantenere e di avere un meccanismo di memorizzazione nella cache affidabile, è saggio assegnare la responsabilità della logica della cache alle classi di cui ti fidi. Cache_Lite è una libreria di memorizzazione nella cache potente ma facile da usare che gestisce attività come il blocco temporaneo dei file di cache, la creazione e la convalida degli stessi, la gestione del buffer di output e la memorizzazione diretta nella cache del risultato di una funzione o di un metodo di classe. Il motivo principale per scegliere questa libreria è l'integrazione relativamente semplice di Cache_Lite in un'applicazione esistente, che richiede solo piccole modifiche al codice.

Cache_Lite è costituito da tre classi principali. La prima è la classe base Cache_Lite, che è responsabile solo della creazione e della lettura dei file della cache e non memorizza nel buffer l'output. Questa classe può essere utilizzata da sola nei casi in cui non è necessario utilizzare il buffering dell'output, ad esempio quando si salva il risultato dell'analisi di un modello da parte di uno script PHP. Gli esempi qui mostrati non utilizzano direttamente la classe Cache_Lite e dimostrano l'uso delle altre due classi. Cache_Lite_Function viene utilizzato per chiamare una funzione o un metodo di classe e quindi memorizzare nella cache i risultati. Ciò può essere utile, ad esempio, per memorizzare nella cache il risultato di una query MySQL. La classe Cache_Lite_Output utilizza le funzioni di controllo dell'output di PHP per intercettare i dati generati da uno script e archiviarli nei file di cache. Ciò consente di eseguire le stesse attività della soluzione precedente.

Impostazioni Cache_Lite

Nella versione attuale della classe (1.1), sono disponibili le seguenti impostazioni:
- cacheDir - directory in cui verranno posizionati i file della cache. Il valore predefinito è la directory in cui viene eseguito lo script;
- caching: questa opzione abilita o disabilita le funzionalità Cache_Lite. Ad esempio, se hai molte richieste a Cache_Lite e durante il debug desideri disattivare la memorizzazione nella cache, impostala su FALSE. Il valore predefinito è VERO.
durata: il parametro contiene la durata della cache predefinita (in secondi);
- fileNameProtection: utilizza la codifica MD5 per generare un nome file di cache. Ciò consente di utilizzare qualsiasi carattere nei nomi dei file e dei gruppi della cache, anche quelli vietati dal file system;
- fileLocking: abilita i meccanismi per bloccare un file con una cache mentre i dati vengono scritti su di esso;
- writeControl - controlla che il file di cache sia stato scritto correttamente subito dopo la fine della scrittura;
- readControl - prima di leggere un file di cache, ne controlla le distorsioni;
- readControlType: questo parametro determina il tipo di meccanismo di lettura del file di cache. Meccanismi disponibili: controllo di ridondanza ciclico, hash MD5 o controllo semplice della lunghezza. Tieni presente che questo meccanismo non è destinato a proteggere i file della cache dall'accesso diretto da parte di utenti non autorizzati. Questo è solo un modo per determinare se un file è danneggiato o meno;
- PearErrorMode: abilita il metodo PEAR per la restituzione degli errori;
- memoryCaching: ogni volta che chiami la cache per scrivere su un file, questo viene scritto nell'array Cache_Lite. saveMemoryCachingState e
getMemoryCachingState vengono utilizzati per accedere alla cache archiviata in memoria tra le richieste. Il vantaggio di questo metodo è che il contenuto della cache può essere archiviato in un singolo file, riducendo il numero di cicli di lettura/scrittura del disco. La cache viene ripristinata direttamente su un array a cui ha accesso lo script;
memoryCachingLimit: il parametro specifica il limite del numero di file di cache che possono essere archiviati in un array in memoria.

svuota la cache

Cahce_Lite contiene un meccanismo efficace per determinare la durata dei file di cache, che crea una buona base per la sicurezza dei file e il loro aggiornamento tempestivo. Tuttavia, ci sono momenti in cui è necessario aggiornare immediatamente il file della cache. Per questi casi, esistono i metodi delete() e clean(). Il metodo Remove() è progettato per rimuovere un file di cache specifico. richiede l'ID della cache e il nome del gruppo a cui appartiene il file. L'esempio seguente eliminerà il file della cache del corpo dall'esempio precedente:

$cache->remove("corpo", "Dinamico");

Il metodo clean() ci consente di eliminare tutti i file nella nostra directory se lo chiamiamo senza parametri. Se passi il nome del gruppo come parametro, tutti i file inclusi in questo gruppo verranno eliminati. Se volessimo rimuovere l'intestazione e il piè di pagina, dovremmo eseguire comandi simili a questi:

$cache->clean("Statico");

I metodi move() e clean() ovviamente devono essere richiamati in risposta ad eventi all'interno dell'applicazione. Ad esempio, se hai un forum, probabilmente dovresti eliminare il file di cache se un utente pubblica un nuovo messaggio. Sebbene questa soluzione sembri interessante, potrebbe comportare alcune modifiche al codice. Se disponi di uno script principale che si collega a ogni pagina dell'applicazione che un visitatore potrebbe visualizzare, puoi semplicemente controllare gli eventi in arrivo, come la variabile $_GET["newPost"], rimuovendo i file di cache richiesti. Ciò ti consentirà di creare un meccanismo di gestione della cache centralizzato. Potresti anche includere questo codice in php.ini.

chiamate alla funzione di memorizzazione nella cache

Poiché i servizi Web sono esposti sulla rete, spesso è una buona idea memorizzare nella cache il risultato in modo che possa essere eseguito localmente anziché eseguire più volte la stessa query lenta. Nel caso più semplice potremmo utilizzare sessioni PHP, ma poiché questa soluzione si basa sulla frequenza dei visitatori, l'apertura di una richiesta per ciascun visitatore sarà comunque lenta. In questi casi, Cache_Lite può essere molto utile.

Il programma di installazione Web PEAR utilizza Cache_Lite per memorizzare nella cache le richieste XML-RPC inviate al server Web PEAR.
Ecco il codice che riceve i dati dal server remoto:

$paesi = $stationInfo->listCountries();

$paese = $stationInfo->searchByCountry($_GET["paese"]);

In entrambi i casi queste chiamate corrispondono ad una richiesta di dati sulla rete. Utilizzando Cache_Lite, potremmo memorizzare nella cache i dati restituiti dal servizio ed essere in grado di riutilizzarli. Ciò eviterebbe ulteriori connessioni di rete non necessarie e aumenterebbe significativamente la velocità di esecuzione. Tieni presente che qui stiamo esaminando solo il codice pertinente al nostro argomento. Per prima cosa abilitiamo Cache_Lite_Function:

// Include PEAR::Cache_Lite_Function
require_once "Cache/Lite/Function.php";

// Imposta i parametri per Cache_Lite_Function
// ATTENZIONE: fileNameProtection = TRUE!
$opzioni = array(
"cacheDir" =>"./cache/",
"fileNameProtection" =>VERO,
"writeControl" =>VERO,
"readControl" =>VERO,
"readControlType" => "strlen",
"defaultGroup" =>"SOAP"
);
// Crea un oggetto della classe Cache_Lite_Function
$cache = nuova Cache_Lite_Function($opzioni);

È importante che il parametro fileNameProtection sia impostato su TRUE. Questo valore è quello predefinito, ma l'ho impostato manualmente specificatamente per enfatizzarne il significato. L'impostazione di questa opzione su FALSE risulterà in un nome file non valido, quindi la memorizzazione nella cache non verrà eseguita.
Successivamente, facciamo una richiesta al nostro client SOAP:

$countries = $cache->call("stationInfo->listCountries");
$paese = $cache->call("stationInfo->searchByCountry",
$_GET["paese"]);

Se viene effettuata una richiesta per la prima volta, Cache_Lite_Function memorizza i risultati come un array serializzato in un file di cache (non devi preoccuparti di questo) e questo file verrà utilizzato per richieste future fino alla scadenza della sua durata. setLifeTime può essere utilizzato per determinare per quanto tempo vivrà un file di cache prima di aggiornarne le informazioni. Il valore predefinito è 1 ora (3600 secondi).

PERA::Cache

In generale, Cach_Lite fornisce un unico sistema facile da usare per risolvere qualsiasi problema relativo alla memorizzazione nella cache. Poiché il livello successivo sono i siti con un traffico particolarmente elevato, dovresti capire PEAR::Cache, il "fratello maggiore" di Cache_Lite. Fornisce inoltre funzionalità di memorizzazione nella cache avanzate, come la memorizzazione nella cache della memoria condivisa come alternativa alla memorizzazione nella cache dei file, oppure l'estensione Msession PHP aiuta memorizzando i dati in una sessione bilanciata, che è particolarmente utile nei server Web bilanciati. Cache_Lite, tuttavia, offre funzionalità più che sufficienti e soddisfa le esigenze della maggior parte dei siti.

come gestire la memorizzazione nella cache lato client utilizzando PHP?

Ora che abbiamo esaminato le opzioni per sovrascrivere la cache lato client, è tempo di esaminare un meccanismo che ci consentirà di controllare la cache lato client utilizzando PHP. Questo approccio funzionerà solo se utilizzi PHP con un server Apache, poiché utilizzeremo la funzione getallheaders per ottenere le intestazioni inviate dal browser. Questa funzione funziona solo in Apache. Se utilizzi PHP 4.3.0 con Apache, è possibile lavorare con le intestazioni HTTP utilizzando le funzioni apache_request_headers e apache_response_headers. La funzione getallheaders è diventata un alias per la nuova funzione apache_request_headers.

Il meccanismo per lavorare con la cache del browser web è ancora una volta HTTP. Sono coinvolte più intestazioni per istruire i browser Web e i server proxy a memorizzare nella cache una pagina in modo indipendente. La situazione è complicata dal fatto che alcuni di essi sono disponibili solo con HTTP 1.1.

controllando le intestazioni HTTP nel tuo browser

Uno strumento semplice ma molto conveniente per controllare le intestazioni di richiesta e risposta è LiveHttpHeaders, un componente aggiuntivo per il browser Mozilla. È importante sapere esattamente quali intestazioni sta inviando il tuo script, soprattutto quando hai a che fare con le intestazioni della memorizzazione nella cache HTTP.
Per semplicità, prenderemo in considerazione solo le intestazioni della cache HTTP 1.0, ovvero Expires, Last-Modified e If-Modified-Since, nonché il codice di stato HTTP 304 (Not Modified).

Altri header disponibili con HTTP 1.1, come Cache-Control ed ETag, hanno lo scopo di fornire un meccanismo esteso che può essere utilizzato insieme allo stato della sessione web, in altre parole, la versione della stessa pagina destinata a un visitatore non autorizzato potrebbe differire in modo significativo da essere visualizzato all'utente autorizzato. Le intestazioni HTTP 1.1 sono state originariamente aggiunte per consentire la memorizzazione nella cache di tali pagine.

scadenza della durata della pagina

L'intestazione più semplice da utilizzare è l'intestazione Expire, che imposta la data di scadenza della pagina. Fino a questo punto, al browser Web è consentito utilizzare una versione della pagina memorizzata nella cache.
Esempio:


funzione setExpires($scadenza)(
header("Scadenza: " . gmdate("D, d M Y H:i:s", time() + $scadenza). "GMT");
}
echo "Questa pagina si autodistruggerà entro 10 secondi
";
eco "Adesso". gmdate("H:i:s") . " GMT
";
eco "
";
?>

L'esempio sopra mostra l'ora GMT corrente e visualizza un collegamento che ti consente di tornare alla pagina. Utilizzando il pulsante Aggiorna del tuo browser, puoi dire al browser che desideri aggiornare la sua cache.

date e orari in HTTP

Le date in HTTP vengono sempre calcolate rispetto al Greenwich Mean Time (GMT). La funzione PHP gmdate è esattamente la stessa funzione di date, tranne per il fatto che compensa automaticamente l'ora GMT in base all'orologio di sistema e alle impostazioni della regione del server. Quando il browser incontra l'intestazione Expires, memorizza la pagina nella cache. Tutte le successive richieste della pagina effettuate prima del tempo TTL specificato utilizzano la versione della pagina memorizzata nella cache, senza effettuare alcuna richiesta al server web.
L'intestazione Expires è semplice da implementare in linea di principio, ma nella maggior parte dei casi, a meno che tu non sia una persona altamente organizzata, non puoi sapere esattamente quando verrà aggiornata una determinata pagina del tuo sito. Poiché il browser contatterà il server solo dopo che la pagina è diventata obsoleta, non c'è modo di dire al browser che una pagina nella sua cache è obsoleta.

orario di cambio pagina

È più pratico utilizzare le intestazioni Last-Modified e If-Modified-Since disponibili in HTTP 1.0. Quando utilizzi questo metodo, devi inviare un'intestazione Last-Modified in risposta a ogni richiesta al tuo script PHP. La prossima volta che il browser richiede la pagina, invierà un'intestazione If-Modified-Since contenente il tempo che lo script può utilizzare per determinare se la pagina è stata aggiornata dall'ultima richiesta. In caso contrario, lo script invia un codice di stato HTTP 304 per indicare che la pagina non è cambiata, senza stampare il contenuto della pagina. Se combini l'approccio dell'ora dell'ultima modifica con un valore temporale già disponibile nella tua applicazione (ad esempio, l'ora dell'articolo di notizie più recente), puoi sfruttare la cache del browser web e scaricare il collegamento dati, salvando le informazioni traffico dal tuo sito, ove possibile, migliorandone le prestazioni.

Fai attenzione quando testi la memorizzazione nella cache eseguita in questo stile: se lo fai in modo errato, potresti far sì che i tuoi visitatori abbiano sempre copie obsolete del tuo sito.

Harry Fuecks, traduzione di Sergey Mullin (SiMM) e Kuzma Feskov.

Non è un segreto che più velocemente un sito viene caricato, più conveniente sarà per gli utenti. Se le pagine si caricano rapidamente, gli utenti non lasceranno il tuo sito e i motori di ricerca tratteranno meglio il tuo sito. Per molti siti Web moderni, il motore di esecuzione degli script dinamici PHP diventa un collo di bottiglia.

Il server web Nginx, se configurato correttamente, può servire istantaneamente un numero enorme di pagine, cosa che non si può dire di PHP; la generazione della pagina può richiedere diversi secondi. Ma PHP può anche essere accelerato utilizzando la memorizzazione nella cache. In questo articolo vedremo come è configurata la memorizzazione nella cache PHP, com'è e perché è necessaria. Utilizzeremo ad esempio una combinazione di php-fpm e Nginx, ma le informazioni contenute nell'articolo sono adatte anche per altre opzioni di installazione.

La particolarità dei linguaggi interpretati è che ogni volta che viene lanciato uno script, l'interprete deve compilare il programma e verificarne gli errori. Ma possiamo andare in giro. Esistono due tipi principali di memorizzazione nella cache:

  • Pagine pronte per la memorizzazione nella cache- la pagina viene generata da PHP, quindi la pagina finita viene fornita all'utente senza accedere a PHP. Ti dirò come farlo usando fastcgi, ma non consiglio di usare questo metodo per Wordpress o altri motori; è meglio memorizzarli nella cache usando plugin speciali;
  • Memorizzazione nella cache del codice byte e delle istruzioni- e questo è già interessante, non viene memorizzata nella cache l'intera pagina, ma solo alcune istruzioni e parti di codice byte che non cambiano quando si richiama lo script. Prima di eseguire uno script, l'interprete deve convertirlo in un formato comprensibile; durante la memorizzazione nella cache, tale conversione viene eseguita solo per la prima esecuzione, quindi viene presa la versione dalla cache;
  • Caching della sessione- per impostazione predefinita, php salva le sessioni utente su file e possiamo velocizzare un po' il suo lavoro se salviamo le sessioni nella RAM.

Caching del bytecode in PHP

A partire da PHP 5.5, all'interprete del linguaggio è stato aggiunto il supporto per la memorizzazione nella cache del bytecode di ZendFramework. Nelle nuove versioni, questa cache ti consente di aumentare notevolmente le prestazioni della tua risorsa; ad esempio, ci sono informazioni che Wordpres e altri motori funzionano quasi due volte più velocemente su PHP 7. Prima di impostare la memorizzazione nella cache php dell'opcode, è necessario installare il relativo pacchetto:

sudo apt installa php-opcache

O per le distribuzioni Red Hat:

sudo yum installa php-opcache

Quindi, per abilitare la memorizzazione nella cache è necessario aggiungere alcune righe a php.ini, puoi anche creare un file separato in /etc/php/conf.d/

vi /etc/php.d/opcache.ini

zend_extension=opcache.so;
opcache.error_log=/var/log/php-fpm/opcache-error.log
opcache.enable=1;
opcache.memory_consumption=256;
opcache.interned_strings_buffer=8;
opcache.max_accelerated_files=4000;
opcache.revalidate_freq=180;
opcache.fast_shutdown=0;
opcache.enable_cli=0;
opcache.revalidate_path=0;
opcache.validate_timestamps=2;
opcache.max_file_size=0;
opcache.file_cache= /var/www/site/opcache;

Diamo un'occhiata al significato di queste righe in modo da sapere quali valori impostare. La prima riga carica l'estensione, qui non è necessario modificare nulla.

  • opcache.error_log- specifica il file per la registrazione del log degli errori, che sarà utile per il debugging;
  • opcache.log_verbosity_level- indica quanto dettagliato deve essere il file di log, valore da 1 a 4;
  • opcache.enable- abilita la memorizzazione nella cache;
  • opcache.enable_cli- abilita la memorizzazione nella cache delle pagine php per la versione console;
  • opcache.memory_consumption- quantità di RAM per l'archiviazione della cache;
  • opcache.max_accelerated_files- numero di script/file che devono essere memorizzati nella cache;
  • opcache.validate_timestamps- controllare l'ora della modifica dei dati nel file di script;
  • opcache.revalidate_freq- frequenza di verifica del parametro precedente;
  • opcache.revalidate_path- impostare a 0 per verificare l'inclusione solo la prima volta;
  • opcache.enable_file_override- memorizza nella cache le richieste per gli attributi dei file, ad esempio l'esistenza, ecc.;
  • opcache.blacklist_nomefile- un elenco di file che non necessitano di essere memorizzati nella cache;
  • opcache.max_file_size- dimensione massima del file di script per la memorizzazione nella cache, 0 - illimitata;
  • opcache.interned_strings_buffer- numero consentito di righe nel buffer;
  • opcache.fast_shutdown- utilizzare un modo rapido per liberare memoria.

Dopo aver salvato tutte le impostazioni, tutto ciò che devi fare è riavviare php o il tuo server web:

systemctl riavvia php-fpm

Per assicurarti che tutto funzioni, potresti voler vedere quali script sono già memorizzati nella cache. A questo scopo è possibile utilizzare lo script opcache-status. Basta salvare lo script nella directory del server Web e quindi concedergli le autorizzazioni:

chmod 777 /var/www/site/opcode.php

http://localhost/opcache.php

Qui puoi vedere statistiche dettagliate sulla memorizzazione nella cache, sulle impostazioni e sulla quantità di memoria occupata.

Memorizzazione delle sessioni in memcached

Per impostazione predefinita, php memorizza le sessioni nel file system; in alcuni casi, puoi velocizzare notevolmente php se trasferisci la memorizzazione delle sessioni dai file alla RAM, ad esempio memcached. Per prima cosa devi installare memcached e la libreria php per lavorarci:

sudo apt install memcached php-memcached

O per i sistemi basati su Red Hat:

sudo yum installa memcached php-memcached

Per prima cosa dobbiamo configurare memcached, aprire il file /etc/sysconfig/memcached e trovare la riga CACHESIZE, qui devi specificare la quantità di RAM allocata per la cache:

vi /etc/sysconfig/memcached

session.save_handler = memcache
session.save_path = "tcp://localhost:11211"

Non resta che riavviare il tuo interprete php:

systemctl riavvia php-fpm

Se vuoi verificare se tutto è memorizzato correttamente nella cache e se c'è qualcosa nella cache, puoi utilizzare phpmemcacheadmin .

Memorizzazione nella cache delle pagine fastcgi

Non consiglio di utilizzare la memorizzazione nella cache fastgci per i siti WordPress perché ci sono plugin speciali che possono controllare con precisione la cache, cancellarla quando necessario e aggiornarla in tempo. Ma in tutti gli altri casi, la cache fastcgi può velocizzare notevolmente il sito. È configurato nella configurazione in cui abiliti fastgci, ad esempio, nella configurazione del server web Nginx. Il modo minimo per configurare la cache fastgci è aggiungere le seguenti righe al blocco del server:

vi /etc/nginx/vhosts/site.conf

fastcgi_cache_path /var/nginx/cachelevels=1:2 keys_zone=MYAPP:100m inattivo=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";

La prima riga configura più parametri contemporaneamente, in primo luogo aggiunge il percorso alla cache, puoi usarne uno qualsiasi, purché la cartella esista e il server web abbia i diritti per scrivervi. La direttiva dei livelli specifica quante sottocartelle ci saranno. La riga successiva specifica quale verrà utilizzata come chiave per la cache. La chiave verrà sottoposta ad hashing in md5.

Ora devi configurare il blocco di elaborazione php:

posizione ~ \.php$ (
fastcgi_pass unix:/var/run/php7-fpm.sock;
fastcgi_index indice.php;
includere fastcgi_params;
fastcgi_cache MIAAPP;
fastcgi_cache_valid 200 60m;
}

Qui accediamo alla zona di memoria MYAPP già configurata e specifichiamo anche una durata della cache di un'ora. Per verificare la memorizzazione nella cache, è possibile visualizzare il contenuto della cartella:

ls -lR /var/nginx/cache/

Con questi metodi, le tue pagine verranno caricate molto più velocemente. Se devi disabilitare la memorizzazione nella cache PHP per singole pagine, crea prima la variabile no_cache con il valore 0:

imposta $no_cache 0;

Quindi controlliamo i parametri necessari e, se corrispondono, impostiamo il valore su 1:

se ($request_method = POST)
{
imposta $no_cache 1;
}

E per finire, passiamo il valore di questa variabile alle seguenti direttive, questo disabiliterà la memorizzazione nella cache quando non è necessaria:

fastcgi_cache_bypass $no_cache;
fastcgi_no_cache $nessuna_cache;

Per ottimizzare il lavoro con la rete, viene utilizzato un meccanismo per salvare i documenti ricevuti tramite HTTP in una cache allo scopo di riutilizzarli senza contattare il server di origine. Un documento salvato nella cache sarà disponibile al successivo accesso, senza scaricarlo dal server di origine, il che ha lo scopo di aumentare la velocità di accesso del client ad esso e ridurre il consumo di traffico di rete.

Le cache stesse sono di due tipi: locali e condivise. Locale è una cache memorizzata direttamente sul disco del client, creata e gestita dal suo browser. Generale è la cache proxy di un'organizzazione o di un provider e può essere costituita da uno o più server proxy. La cache locale è presente, probabilmente in ogni browser, una parte significativa delle persone che utilizzano Internet utilizza quelli comuni. E se una piccola parte dei siti viene ora valutata in base al consumo di traffico, la velocità di caricamento è un criterio importante da tenere in considerazione durante lo sviluppo del progetto web.
Per le pagine dinamiche create tramite un programma PHP, la memorizzazione nella cache sembrerebbe dannosa. Il contenuto della pagina è formato su richiesta dell'utente in base a qualsiasi fonte di dati. Tuttavia, la memorizzazione nella cache può essere utile. Gestendolo, puoi rendere più confortevole per l'utente il lavoro con il tuo server consentendo il caricamento di determinate pagine dalla cache, impedendo così che vengano ricaricate dal tuo server e risparmiando tempo e traffico all'utente.

Memorizzare nella cache o no?

La possibilità di salvare una pagina nella cache è determinata dal dinamismo delle informazioni nell'origine dati. Pertanto, la necessità di utilizzare una cache viene determinata da te in base alla durata pianificata della pagina.

Se stiamo parlando di formare un campione dal database (ad esempio, cercando una parola inserita dall'utente), allora tale pagina deve essere richiesta al server ad ogni chiamata senza utilizzare la cache, poiché il numero di varianti della le parole richieste sono enormi e se abbiamo a che fare anche con la modifica della serie di dati, la memorizzazione nella cache è inutile. Oppure stiamo parlando di formare, ad esempio, un programma di visitatori in entrata (che cambia con ogni visita, cioè con quasi ogni chiamata), quindi la memorizzazione nella cache è semplicemente dannosa.

Tuttavia, se parliamo dello stesso grafico ma per ieri, allora si consiglia la memorizzazione nella cache, poiché i dati non cambieranno più e possiamo risparmiare noi stessi e l'utente risorse e tempo per caricare tali pagine inserendole in una cache locale o condivisa . In continuità con questa situazione, la formazione del programma non avviene in tempo reale, ma ogni ora. Qui puoi prevedere in anticipo la data di scadenza dei dati generati.

Principi generali per la memorizzazione delle pagine nella cache

Un programma PHP può controllare la memorizzazione nella cache dei risultati del suo lavoro formando campi aggiuntivi nell'intestazione della risposta HTTP chiamando la funzione Header().
Diverse affermazioni generali tipiche non solo dei programmi PHP:

  • Le pagine inviate tramite POST non vengono mai memorizzate nella cache.
  • Le pagine richieste tramite GET e contenenti parametri (l'URL contiene "?") non vengono archiviate nella cache se non diversamente specificato.

Pertanto, nella maggior parte delle situazioni non è necessario aggiungere ulteriori istruzioni al programma. I punti principali a cui prestare attenzione si possono ridurre a due:

  • disabilitare la memorizzazione nella cache dei documenti memorizzati nella cache per impostazione predefinita
  • Memorizzazione nella cache di documenti che non sono memorizzati nella cache per impostazione predefinita.

Impedisci la memorizzazione nella cache dei documenti memorizzati nella cache per impostazione predefinita

Questo problema si presenta con gli script PHP che vengono richiamati senza parametri o che sono indici di directory, ma generano dati personali per l'utente (ad esempio sulla base di cookie o user agent) o funzionano sulla base di dati che cambiano rapidamente. Secondo la specifica HTTP/1.1 possiamo gestire i seguenti campi:

Scade
Specifica la data di scadenza del documento. Impostandolo nel passato determina che la cache sarà disabilitata per questa pagina.

Controllo della cache: nessuna cache
Gestione della cache. Il valore no-cache determina se la cache di questa pagina è disabilitata. Per la versione del protocollo HTTP/1.0 si applica “Pragma: no-cache”.

Ultima modifica
Data dell'ultima modifica del contenuto. Il campo è rilevante solo per le pagine statiche. Apache sostituisce questo campo con il valore del campo Data per le pagine generate dinamicamente, incluse le pagine contenenti SSI.

Il sito web www.php.net fornisce il seguente codice per disabilitare la memorizzazione nella cache.

header("Scadenza: lunedì 26 luglio 1997 05:00:00 GMT"); // Data nel passato
header("Ultima modifica: " . gmdate("D, d M Y H:i:s") . " GMT"); // sempre modificato
header("Cache-Control: no-cache, must-revalidate"); //HTTP/1.1
header("Pragma: no-cache"); //HTTP/1.0

Tuttavia, questa intestazione è ridondante. Nella maggior parte dei casi è sufficiente:

Per contrassegnare un documento come "obsoleto" è necessario impostare Scadenza uguale al campo Data.
header("Scadenza: " . gmdate("D, d M Y H:i:s") . " GMT");

Ebbene, non dobbiamo dimenticare che anche i moduli richiesti tramite POST non sono soggetti a memorizzazione nella cache.

Memorizzazione nella cache di documenti che non sono memorizzati nella cache per impostazione predefinita

Il problema inverso può sembrare a prima vista assurdo. Ma anche di questo ce n’è bisogno. Oltre a minimizzare semplicemente il traffico, quando sviluppi un programma web, dovresti prendere in considerazione il comfort dell’utente con esso. Ad esempio, alcune pagine del tuo server sono formate sulla base di dati statici di grandi dimensioni. La possibilità di includerli nella cache migliorerà significativamente la velocità del server per l'utente e ti libererà parzialmente da numerose generazioni ripetute di tale pagina. Intestazione che consente il salvataggio sui server proxy:

Articolo correlato: Promozione sui motori di ricerca di un negozio online in Yandex e Google: lista di controllo per il controllo dei fattori di ranking


Se una pagina tiene conto delle informazioni memorizzate nel browser dell’utente (tipo e versione del browser, chiavi, autorizzazione, ecc.), tale pagina non può essere salvata nel proxy, ma può essere salvata nella cache del browser locale:

header("Controllo cache: privato");

Memorizzazione nella cache fino alla scadenza della validità

Le soluzioni sopra descritte sono abbastanza semplici, sebbene adatte alla maggior parte dei problemi. Ma il protocollo HTTP/1.1 dispone di strumenti per una gestione più dettagliata della cache delle pagine e alcune attività richiedono l’uso di questi meccanismi. Ad esempio, applicazioni web che funzionano con grandi volumi di dati e dinamiche prevedibili. La correttezza dei dati può essere determinata sia dalla data dell'aggiornamento previsto che da modifiche del contenuto. In questi casi vengono utilizzate intestazioni di controllo della cache diverse.

Caching dell'aggiornamento predittivo

Consideriamo un esempio: un listino prezzi aggiornato il lunedì. Sai in anticipo che il contenuto della pagina può essere archiviato nella cache fino all'inizio della nuova settimana, cosa che dovrebbe essere indicata nell'intestazione della risposta per garantire il comportamento desiderato della pagina nella cache.
Il compito principale è ottenere la data del prossimo lunedì nel formato RFC-1123

$dt_tmp=getdate(data("U"));
header("Scadenza: " . gmdate("D, d M Y H:i:s", date("U")-(86400*($dt_tmp["wday"]-8))) . " GMT");
header("Controllo cache: pubblico");

Questo metodo può controllare efficacemente il comportamento di una pagina nella cache ed è applicabile a un gran numero di pagine: in un modo o nell'altro è possibile selezionare intervalli di tempo durante i quali il contenuto della pagina rimane costante. La realtà è che le pagine della maggior parte dei siti dinamici hanno una certa durata in base alla quale lo sviluppatore può creare un'esperienza più piacevole per l'utente.

Un altro approccio, utilizzato quando le informazioni vengono aggiornate più rapidamente e allo stesso tempo c'è un traffico elevato verso il server (altrimenti la memorizzazione nella cache non sarà efficace) è quello di utilizzare l'intestazione Cache-control: max-age=seconds, che determina il tempo dopo il quale il il documento è considerato scaduto e ha una priorità più alta nel calcolo della "freschezza" del documento.

Cacheè uno speciale buffer intermedio con accesso molto veloce, contenente i dati che con maggiore probabilità verranno richiesti.

Cos'è la memorizzazione nella cache?

Per ottimizzare il lavoro con la rete, viene utilizzato un meccanismo per salvare i documenti ricevuti una volta tramite HTTP nella cache per il loro riutilizzo, senza contattare il server di origine. Il documento salvato nella cache sarà disponibile al successivo accesso, senza scaricarlo dal server di origine. Questo è progettato per aumentare la velocità di accesso del client ad esso, nonché per ridurre il consumo del traffico di rete.

Oggi esistono due tipi di cache: locale e condivisa.

  • Locale: una cache memorizzata sul disco del cliente, creata e gestita dal suo browser Internet.
  • Generale è la cache del server proxy del provider, può essere composta da uno o più server proxy.

Esiste una cache locale, probabilmente in ogni browser Internet; quelli comuni sono utilizzati dalla maggior parte delle persone che utilizzano Internet. E se oggi una piccola parte dei siti web viene valutata in base al consumo di traffico, allora la velocità di caricamento è un criterio molto importante da tenere in considerazione quando si sviluppa il proprio progetto web.

Per le pagine dinamiche create come risultato di un'applicazione PHP, la memorizzazione nella cache sembra essere molto dannosa. Il contenuto della pagina è formato su richiesta dell'utente in base a una specifica fonte di informazioni. Tuttavia, la memorizzazione nella cache può essere utile. Gestendolo, puoi rendere il lavoro con il tuo server molto più conveniente per l'utente, consentendo il caricamento di pagine specifiche dalla cache, impedendo così che vengano ricaricate dal server e risparmiando traffico e tempo all'utente.

Principi chiave per la memorizzazione delle pagine nella cache

Un'applicazione PHP può controllare la memorizzazione nella cache dei risultati del proprio lavoro formando campi aggiuntivi nell'intestazione della risposta HTTP chiamando la speciale funzione Header().

Alcune affermazioni generali che non si limitano alle applicazioni PHP:

  • Le pagine trasmesse tramite POST non vengono mai salvate nella cache.
  • Le pagine richieste tramite GET e contenenti parametri (l'URL contiene "?") non vengono salvate nella cache se non diversamente specificato.

Nella maggior parte dei casi non è necessario aggiungere ulteriori istruzioni all'applicazione. Punti chiave a cui prestare attenzione:

  • vietare la memorizzazione nella cache dei documenti memorizzati nella cache per impostazione predefinita;
  • memorizzare nella cache i documenti che non sono memorizzati nella cache per impostazione predefinita.

Divieto di memorizzare nella cache i documenti (che sono memorizzati nella cache per impostazione predefinita)

Questo problema si presenta con gli script PHP che vengono richiamati senza parametri o che sono indici di directory, ma generano informazioni personali per l'utente (ad esempio sulla base dello user agent o dei cookie) o funzionano sulla base di informazioni che cambiano rapidamente. Secondo la specifica HTTP/1.1 possiamo gestire i seguenti campi:

  1. Scadenza: specifica la data di scadenza di un documento specifico. Impostandolo nel passato determina che la cache sarà disabilitata per questa pagina.
  2. Controllo cache: no-cache - controllo cache. Il valore no-cache determina se la cache di questa pagina è disabilitata. Per la versione del protocollo HTTP/1.0 qui vale "Pragma: no-cache".
  3. Ultima modifica è la data dell'ultima modifica del contenuto specifico. Il campo viene utilizzato esclusivamente per le pagine statiche. Apache sostituisce questo campo con il valore del campo Data per le pagine generate dinamicamente, in particolare per le pagine che contengono SSI.

Per disabilitare la memorizzazione nella cache basta scrivere:

Per contrassegnare un documento come "obsoleto", è necessario impostare Scadenza uguale al campo Data.

Header("Scadenza: " . gmdate("D, d M Y H:i:s") . " GMT");

Non dovremmo inoltre dimenticare che i moduli richiesti tramite POST non possono essere memorizzati nella cache.

Caching dell'aggiornamento predittivo

Consideriamo un esempio: il listino prezzi viene aggiornato il lunedì. Sai in anticipo che il contenuto della pagina può essere archiviato nella cache fino alla settimana successiva, che dovrebbe essere indicata nell'intestazione della risposta, garantendo il comportamento necessario della pagina nella cache.

Il compito principale qui è ottenere la data di lunedì prossimo sotto forma di RFC-1123.

$dt_tmp=getdate(data("U")); header("Scadenza: " . gmdate("D, d M Y H:i:s", date("U")-(86400*($dt_tmp["wday"]-8))) . " GMT"); header("Controllo cache: pubblico");

Questo metodo può controllare in modo molto efficace il comportamento di una pagina nella cache. È possibile selezionare intervalli di tempo speciali durante i quali il contenuto di una determinata pagina rimane costante.

Un altro approccio, che viene utilizzato quando si aggiornano i dati più rapidamente e allo stesso tempo c'è un traffico elevato verso il server (altrimenti la memorizzazione nella cache non sarà efficace) è quello di utilizzare un'intestazione speciale Cache-control: max-age=seconds, che determina il tempo trascorso cui il documento è considerato obsoleto e ha una priorità molto più alta nel calcolo della freschezza di un particolare documento.

Se pubblichi notizie a intervalli di 60 minuti:

Header("Controllo cache: pubblico"); header("Controllo cache: max-age=3600");

Implementazione della memorizzazione nella cache in PHP

È necessario creare due file speciali. Il primo eseguirà l'output della cache e il secondo creerà la cache.

Cominciamo con il primo file, che chiameremo read_cache.php.

In questo script, otteniamo il nome del file, quindi controlliamo se esiste una cache di questo tipo, quindi lo produciamo e finiamo il lavoro o apriamo un buffer in cui inseriremo tutto l'output dello script.

Ora creiamo un file speciale write_cache.php. Scriverà su un file ciò che si è accumulato nel buffer.

Ora in qualsiasi file PHP responsabile dell'output, puoi abilitare la memorizzazione nella cache:

Ora puoi iniziare a memorizzare nella cache tutte le pagine problematiche. Tuttavia, ricorda che mentre la cache è attiva, l'utente non vedrà alcun aggiornamento. A questo proposito, esegui il caching in PHP solo per quelle pagine che vengono aggiornate molto raramente.

Ai vecchi tempi, quando creare siti Web era semplice come digitare alcune pagine HTML, inviare pagine Web al browser era semplicemente una questione di invio di un file da parte del server Web. I visitatori del sito potevano vedere queste piccole pagine di solo testo quasi istantaneamente (ad eccezione degli utenti di modem lenti). Una volta caricata la pagina, il browser la memorizza nella cache da qualche parte sul computer locale in modo che, se la pagina viene richiesta nuovamente, possa recuperare la versione locale dalla cache, inviando solo una breve richiesta per garantire che la pagina sul server non sia stata caricata. stato modificato. Le richieste sono state elaborate rapidamente e nel modo più efficiente possibile e tutti erano contenti (tranne quelli che utilizzavano modem a 9600 baud).

L'avvento delle pagine web dinamiche ha cambiato le cose in peggio, interrompendo di fatto questo modello di servizio delle pagine web a causa di due problemi:

Quando il server riceve una richiesta per una pagina Web dinamica, vengono eseguite alcune elaborazioni intermedie, come l'analisi dello script da parte del motore PHP, che deve essere completata. Grazie a ciò, otteniamo un ritardo prima che il server web inizi a inviare l'output al browser. Per un semplice script PHP questo non è significativo, ma per un'applicazione più complessa il motore PHP può eseguire molte azioni prima che la pagina sia pronta per essere inviata. Questi passaggi aggiuntivi comportano un notevole ritardo tra le richieste degli utenti e le pagine effettivamente visualizzate nei loro browser.

Un tipico server web, come Apache, utilizza il tempo di modifica del file per comunicare correttamente al browser web lo stato della cache della pagina richiesta. Per le pagine Web dinamiche, lo script PHP effettivo può cambiare solo occasionalmente, mentre il contenuto visualizzato, eventualmente residente in un database, cambia frequentemente. Il server Web non ha modo di sapere se sono state apportate modifiche al database, ma non invia la data dell'ultima modifica. Se il client (browser) non riceve alcuna indicazione su quanto tempo i dati sono corretti, presuppone che la prossima volta dovrà richiedere una nuova pagina. Il server Web risponderà sempre con una versione aggiornata della pagina, indipendentemente dal fatto che i dati siano cambiati. Per evitare questo inconveniente, la maggior parte degli sviluppatori web utilizza meta tag o intestazioni HTTP per indicare al browser di non utilizzare mai la versione memorizzata nella cache della pagina. Tuttavia, ciò annulla la naturale capacità del browser Web di memorizzare nella cache le pagine Web e presenta alcuni svantaggi significativi. Ad esempio, il contenuto di una pagina dinamica può cambiare una volta al giorno, quindi il vantaggio ottenuto dal fatto che il browser memorizzi la pagina nella cache anche per 24 ore è evidente.

Di solito per piccole applicazioni PHP è del tutto possibile ignorare l'esistenza di questi problemi, tuttavia, con l'aumento della complessità e del traffico del tuo sito, potresti riscontrare problemi. Tuttavia, entrambi questi problemi possono essere risolti, il primo mediante il caching lato server, il secondo gestendo il caching lato client dall'interno dell'applicazione. L'approccio che adotterai per risolvere i problemi dipenderà dalla tua applicazione, ma in questo capitolo vedremo come risolvere entrambi i problemi utilizzando PHP e alcune classi della libreria PEAR.

Tieni presente che il capitolo Caching tratta solo le soluzioni implementate utilizzando PHP. Non devono essere confuse con le soluzioni di memorizzazione nella cache degli script, che funzionano ottimizzando e memorizzando nella cache gli script PHP compilati. Questo gruppo può includere Zend Accelerator, ionCube PHP Accelerator, Turck MMCache/eaccelerator, APC.

Come posso impedire ai browser di memorizzare nella cache una pagina?

Prima di esaminare le tecniche di memorizzazione nella cache di client e server, dobbiamo innanzitutto capire come impedire ai browser Web (e ai server proxy) di memorizzare nella cache le pagine. Il modo principale per raggiungere questo obiettivo è utilizzare i meta tag HTML:

"Lunedì 26 luglio 1997 05:00:00 GMT" />

Inserendo una data passata nel meta tag Expires, indichi al browser che la copia cache della pagina è sempre obsoleta. Ciò significa che il browser non dovrebbe mai memorizzare la pagina nella cache. Meta tag Pragma: no-cache è una convenzione abbastanza ben supportata seguita dalla maggior parte dei browser web. Una volta rilevato questo tag, di solito non memorizzano la pagina nella cache (anche se non esiste alcuna garanzia, questa è solo una convenzione).

Sembra una buona cosa, ma ci sono due problemi con l'utilizzo dei meta tag:

Se il tag non esisteva quando la pagina è stata richiesta per la prima volta dal browser, ma appare successivamente (ad esempio, hai modificato il file include pageheader.php che è l'intestazione di ogni pagina web), il browser rimarrà beatamente inconsapevole e utilizzerà il suo copia cache dell'originale.

I server proxy che memorizzano nella cache le pagine Web, come un ISP condiviso, non esamineranno affatto direttamente il contenuto del documento HTML. Si affidano invece solo al server web da cui provengono i documenti e al protocollo HTTP. In altre parole, il browser web potrebbe pensare che non dovrebbe memorizzare nella cache la pagina, ma il server proxy tra il browser e il server web probabilmente non lo sa e continuerà a inviare la stessa pagina, ora obsoleta, al client .

Un approccio migliore è utilizzare il protocollo HTTP direttamente utilizzando la funzione di intestazione PHP, equivalente ai due meta tag sopra:

intestazione(); header("Pragma: no-cache");

Possiamo fare un ulteriore passo avanti utilizzando l'intestazione Cache-Control, che è compatibile con i browser che supportano HTTP 1.1:

intestazione ( "Scadenza: lunedì 26 luglio 1997 05:00:00 GMT") ; intestazione( "Controllo cache: no-store, no-cache, deve essere riconvalidato") ; intestazione( "Controllo cache: controllo successivo=0, controllo preliminare=0", FALSO ) ; header("Pragma: no-cache");

Ciò garantisce che nessun browser Web o server proxy intermedio memorizzi la pagina nella cache, quindi i visitatori ricevono sempre la versione più aggiornata del contenuto. In effetti, la prima intestazione dovrebbe essere autonoma; questo è il modo migliore per garantire che la pagina non venga memorizzata nella cache. Intestazioni Controllo della cache E Pragma aggiunto a scopo di “assicurazione”. Anche se non funzionano con tutti i browser o proxy, rilevano alcuni casi in cui Scade non funziona come previsto (ad esempio, se la data sul computer del cliente non è impostata correttamente).

Naturalmente, evitare del tutto la memorizzazione nella cache ci pone di fronte ai problemi di cui abbiamo discusso all'inizio di questo capitolo. Vedremo ora come risolvere questi problemi. Internet Explorer e memorizzazione nella cache dei download di file

La nostra discussione sul PDF nel capitolo 3, Tipi di contenuto alternativi, ha spiegato che possono sorgere problemi quando si ha a che fare con la memorizzazione nella cache e il download dei file. Se, quando si esegue il download di un file tramite uno script PHP, intestazioni come Disposizione contenuto: allegato, nome file=mioFile.pd per Disposizione contenuto: inline, nomefile=mioFile.pdf, avrai problemi con Internet Explorer se dici al browser di non memorizzare la pagina nella cache.

Internet Explorer gestisce i download in un modo piuttosto insolito, effettuando due richieste al sito web. La prima richiesta scarica il file e lo memorizza nella cache finché non viene effettuata la seconda richiesta (senza memorizzare la risposta). Questa richiesta fa sì che il file venga trasferito all'utente finale in base al tipo di file (ad esempio, avvia Acrobat Reader se il file è un documento PDF). Ciò significa che se invii intestazioni che impediscono al browser di memorizzare nella cache la pagina, Internet Explorer eliminerà il file tra la prima e la seconda richiesta, senza risultato per l'utente finale. Se il file che stai servendo con uno script PHP non cambia, una delle soluzioni più semplici è rimuovere le intestazioni di “inibizione della cache” dallo script.

Se il file scaricato cambia regolarmente (ovvero desideri che il browser scarichi la versione più recente), dovresti utilizzare l'intestazione Ultima modifica, di cui si parlerà più avanti in questo capitolo, e garantire che il tempo di modifica tra due richieste consecutive non cambi. È necessario farlo in modo da non influire sugli utenti dei browser che gestiscono correttamente i download. Una soluzione in questo caso sarebbe quella di archiviare il file sul tuo server web e fornire un semplice collegamento ad esso, consentendo al server web di segnalare le intestazioni della cache per te. Naturalmente questa soluzione potrebbe non essere accettabile se si presuppone l'accesso autorizzato al file; questa soluzione consente il caricamento diretto del file salvato.

Come posso acquisire i dati lato server per la memorizzazione nella cache?

È tempo di vedere come possiamo ridurre la latenza utilizzando la memorizzazione nella cache dell'output lato server. L'approccio generale è iniziare a servire la pagina come al solito, eseguendo query sul database e così via in PHP. Tuttavia, prima di inviare il risultato al browser, lo acquisiamo e salviamo la pagina finale, ad esempio, in un file. Alla richiesta successiva, lo script PHP verifica innanzitutto la presenza di una versione della pagina memorizzata nella cache. Se esiste, lo script invia la versione memorizzata nella cache al browser, eliminando così il ritardo nella ricreazione della pagina.

Qualche parola sulla memorizzazione nella cache utilizzando i modelli

I motori di template come Smarty parlano spesso di memorizzazione nella cache dei template. In genere, questi motori offrono un meccanismo integrato per salvare una versione compilata del modello (ovvero, generare codice sorgente PHP dal modello), che ci evita di dover analizzare il modello ogni volta che viene richiesta una pagina. Questo non deve essere confuso con il caching dell'output, che si riferisce alla memorizzazione nella cache dell'HTML fornito (o di altro output) che PHP invia al browser. Puoi utilizzare con successo entrambi i tipi di memorizzazione nella cache contemporaneamente sullo stesso sito.

Vedremo ora il meccanismo di memorizzazione nella cache integrato di PHP che utilizza il buffering dell'output, che puoi utilizzare indipendentemente da come crei il tuo contenuto (con o senza modelli). Considera una situazione in cui il tuo script visualizza il risultato utilizzando, ad esempio, echo o print per inviare i dati direttamente al browser. In questo caso, puoi utilizzare le funzioni di controllo dell'output di PHP per archiviare i dati nella memoria buffer, su cui lo script PHP ha accesso e controllo.

Ecco un semplice esempio:

Esempio 5.1. 1.php

Ob_inizio(); // Emette del testo (che viene salvato nel buffer); eco "1. Lo inviamo nel buffer
"
; // Interrompe il buffering e cancella il buffer di output ob_end_clean(); // Emette del testo come al solito eco "2. Uscita normale
"
; // Stampa il contenuto del buffer echo $buffer;

Il buffer stesso memorizza l'output come una stringa. Quindi, nello script sopra, iniziamo il buffering con ob_start e usiamo echo per produrre qualcosa. Utilizziamo quindi ob_get_contents per recuperare i dati memorizzati nel buffer dall'echo istruzione e memorizzarli in una stringa. La funzione ob_end_clean interrompe il buffering dell'output e ne svuota il contenuto; in alternativa, ob_end_flush può essere utilizzato per svuotare il contenuto del buffer.

Lo script sopra restituirà:

2. Uscita normale 1. Invia questo al buffer

In altre parole, abbiamo catturato l'output del primo eco, quindi lo abbiamo inviato al browser dopo il secondo eco. Come puoi vedere da questo semplice esempio, il buffering dell'output è uno strumento molto potente per dare forma al tuo sito, fornisce una soluzione di caching, come vedremo tra poco, ed è un ottimo modo per nascondere gli errori ai visitatori del tuo sito (vedi Capitolo 10, Gestione degli errori). Fornisce inoltre un'opzione alternativa per il reindirizzamento del browser in situazioni come l'autenticazione dell'utente.

Intestazioni HTTP e buffer di output

Il buffering dell'output può aiutare a risolvere il problema più comune con la funzione header, per non parlare di session_start e set_cookie. In genere, se chiami una di queste funzioni dopo che la pagina ha iniziato il rendering, riceverai un brutto messaggio di errore. Quando il buffering dell'output è abilitato, l'unico tipo di output che evita il buffering sono le intestazioni HTTP. Usando ob_start proprio all'inizio dell'esecuzione della tua applicazione, puoi inviare intestazioni in qualsiasi punto del programma che preferisci senza incontrare i soliti errori. Quindi, una volta che sei sicuro di non aver bisogno di stampare altre intestazioni HTTP, puoi stampare subito il contenuto della pagina dal buffer. (nota del traduttore: va notato che tale utilizzo di questa funzione è estremamente ingiustificato. Nella maggior parte dei casi, la necessità di utilizzare il buffering dell'output per eliminare errori di questo tipo semplicemente non esiste e tutto può essere facilmente corretto con una corretta progettazione dell'applicazione )

Utilizzo del buffering di output per la memorizzazione nella cache lato server

Hai già visto un esempio base di buffering dell'output, ora il passaggio successivo è il salvataggio del buffer in un file:

Esempio 5.2. 2.php

// Se esiste una versione memorizzata nella cache... if (file_esiste ("./cache/2.cache" ) ) ( // Legge e genera il file leggifile("./cache/2.cache" ); Uscita(); ) // Avvia il buffering dell'output ob_inizio(); // Visualizza il resto dell'HTML ?> Pagina memorizzata nella cache "http://www.php.net/outcontrol">Funzioni di controllo dell'output // Ottiene il contenuto del buffer$buffer = ob_get_contents(); // Interrompe il buffering e visualizza il buffer ob_end_flush(); // Salvataggio di un file di cache con contenuto$fp = fopen("./cache/2.cache" , "w" ) ; fwrite($fp, $buffer); fclose($fp);

Innanzitutto, lo script precedente controlla se esiste una versione della pagina nella cache e, se esiste, lo script la legge e la visualizza. Altrimenti, utilizza il buffering di output per creare una versione memorizzata nella cache della pagina. Viene salvato come file dopo aver utilizzato ob_end_flush per visualizzare la pagina all'utente.

Il file 2.cache contiene una copia esatta dell'HTML fornito dallo script:

"http://www.w3.org/1999/xhtml"> > > Pagina memorizzata nella cache > "testo/html; set di caratteri=windows-1251" /> > > Questa pagina viene memorizzata nella cache utilizzando PHP "http://www.php.net/outcontrol"> Funzioni di controllo dell'uscita > > >

Blocca il buffering

Un approccio semplificato memorizza nella cache il buffer di output come una singola pagina. Tuttavia, questo approccio ti priva del reale potere fornito dalle funzionalità di gestione dell'output di PHP per migliorare le prestazioni del tuo sito variando di conseguenza la durata dei tuoi contenuti.

Senza dubbio, alcune parti della pagina che invii al tuo visitatore cambiano molto raramente, come l'intestazione, il menu e il piè di pagina. Tuttavia, altre parti, come le tabelle contenenti le discussioni nei forum, possono cambiare con una certa frequenza. Il buffering dell'output può essere utilizzato per memorizzare nella cache sezioni di una pagina in file separati, quindi costruire la pagina da essi: una soluzione che elimina la necessità di ripetute query sul database, cicli while, ecc. Puoi assegnare a ciascun blocco di pagina una data di scadenza dopo la quale il file di cache viene ricreato oppure puoi anche includere un meccanismo nell'applicazione che eliminerà il file di cache ogni volta che il contenuto in esso archiviato viene modificato.

Ecco un esempio che dimostra questo principio:

Esempio 5.3. 3.php (inizio)

/** * Voce del file di cache * @param string content – ​​contenuto del buffer * @param string filename – nome del file utilizzato durante la creazione del file di cache * @return void */ funzione writeCache($contenuto, $nomefile) ( $fp = fopen ("./cache/" . $nomefile, "w" ) ; fwrite ($fp, $contenuto ) ; fclose ($fp ) ; ) /** * Controllo dei file di cache * @param string filename – nome del file di cache da controllare * @param int expiry – “età” massima del file in secondi * @return contenuto cache misto o false */ funzione readCache($nomefile , $scadenza ) ( if (file_exists ("./cache/" . $nomefile ) ) ( if ((time () - $scadenza ) > filemtime ("./cache/" . $nomefile ) ) return FALSO ; $cache = file ("./cache/" . $nomefile ) ; return implode ("" , $cache ) ; ) return FALSO ; )

Le prime due funzioni che abbiamo definito sono writeCache E readCache, vengono utilizzati rispettivamente per creare file di cache e verificarne l'esistenza. La funzione writeCache riceve i dati da memorizzare nella cache nel suo primo argomento e il nome del file da utilizzare durante la creazione del file di cache. La funzione readCache riceve il nome del file di cache come primo parametro, insieme al tempo in secondi dopo il quale il file di cache dovrebbe essere considerato obsoleto. Se trova il file di cache valido, lo script ne restituirà il contenuto, altrimenti restituirà FALSE per indicare che il file di cache non esiste o non è aggiornato.

In questo esempio ho utilizzato un approccio procedurale. Tuttavia, non consiglio di farlo in pratica, poiché si otterrebbe un codice molto confuso (vedere le soluzioni successive per un'alternativa migliore) e probabilmente causerebbe problemi di blocco dei file (ad esempio, cosa succede quando qualcuno accede alla cache mentre viene aggiornato?).

Continuiamo con questo esempio. Una volta avviato il buffering dell'output, inizia l'elaborazione. Lo script chiama prima readCache per vedere se esiste il file 3_header.cache, che contiene l'intestazione della pagina: l'intestazione HTML e l'inizio del corpo. Utilizziamo la funzione data di PHP per restituire l'ora in cui la pagina è stata effettivamente generata, in modo da poter vedere i vari file di cache in azione quando viene eseguito il rendering della pagina.

Esempio 5.4. 3.php (continua)

// Avvia il buffering dell'output ob_inizio(); // Elabora l'intestazione if (!$header = readCache("3_header.cache" , 604800 ) ) ( // Visualizza l'intestazione ?>"-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> "http://www.w3.org/1999/xhtml"> Pagina memorizzata nella cache blocco per blocco "testo/html; set di caratteri=windows-1251" /> Orario di creazione dell'intestazione:

Cosa succede quando il file della cache non viene trovato? Parte del contenuto viene emesso e assegnato a una variabile utilizzando ob_get_contents, dopodiché il buffer viene cancellato dalla funzione ob_clean. Ciò ci consente di acquisire l'output pezzo per pezzo e abbinarlo ai singoli file di cache utilizzando writeCache. Il titolo della pagina è ora memorizzato come file che può essere utilizzato senza il nostro intervento nella ricostruzione della pagina. Torniamo per un secondo all'inizio dell'istruzione condizionale. Quando abbiamo chiamato readCache gli abbiamo passato una durata della cache di 604800 secondi (una settimana), readCache utilizza il tempo di modifica del file di cache per determinare se il file di cache è ancora valido.

Per il contenuto (corpo) della pagina utilizzeremo ancora lo stesso procedimento. Tuttavia, questa volta quando chiameremo readCache utilizzeremo una durata della cache di cinque secondi, il file della cache verrà modificato ogni volta che è “più vecchio” di 5 secondi:

Esempio 5.5. 3.php (continua)

// Elabora il corpo della pagina if (!$body = readCache("3_body.cache" , 5 ) ) ( echo "Tempo di creazione del corpo:". data ("H:i:s" ). "
" ; $corpo = ob_get_contents () ; ob_clean () ; writeCache($corpo, "3_body.cache" ) ; )

Il piè di pagina può essere modificato in modo efficace allo stesso modo dell'intestazione. Successivamente, il buffering dell'output si interrompe e viene visualizzato il contenuto di tre variabili contenenti i dati della pagina:

Esempio 5.6. 3.php (fine)

// Gestisce il piè di pagina if (!$footer = readCache("3_footer.cache" , 604800 ) ) ( ?> Ora di creazione del piè di pagina:
// interrompe il buffering ob_end_clean(); // Visualizza il contenuto della pagina echo $intestazione . $corpo. $ piè di pagina;

Il risultato finale è simile a questo:

Ora di creazione dell'intestazione: 17:10:42 Ora di creazione del corpo: 18:07:40 Ora di creazione del piè di pagina: 17:10:42

L'intestazione e il piè di pagina vengono aggiornati settimanalmente, mentre il corpo viene modificato quando è più vecchio di 5 secondi.

Il diagramma a blocchi nella Figura 5.1 riassume la metodologia del buffering a blocchi.

Figura 5.1. Schema a blocchi del buffering dell'uscita a blocchi

Buffer nidificati

Puoi nidificare un buffer all'interno di un altro praticamente indefinitamente semplicemente chiamando ob_start ripetutamente. Questo può essere utile se hai molte operazioni che utilizzano il buffer di output, ad esempio alcune che rilevano messaggi di errore PHP, altre che si occupano della memorizzazione nella cache. È necessario assicurarsi che ob_end_flush o ob_end_clean venga chiamato ogni volta che viene utilizzato ob_start.

Come posso implementare un semplice sistema di caching lato server?

Ora che abbiamo compreso le idee alla base del buffering dell'output, è tempo di vedere come possiamo mettere in atto questo processo in un modo che sia facile da mantenere. Per fare ciò, utilizzeremo un piccolo aiuto da PEAR::CacheLite (negli esempi qui è stata utilizzata la versione 1.1).

Cache_Lite

Come ho detto, nell'interesse di rendere il codice più facile da mantenere e di avere un meccanismo di memorizzazione nella cache affidabile, è saggio assegnare la responsabilità della logica della cache alle classi di cui ti fidi. Cache_Lite è una libreria di caching potente ma facile da usare che si occupa di attività come bloccare temporaneamente i file di cache, crearli e convalidarli, gestire il buffer di output e memorizzare direttamente nella cache il risultato di una funzione o di un metodo di classe. Il motivo principale per scegliere questa libreria è l'integrazione relativamente semplice di Cache_Lite in un'applicazione esistente, che richiede solo piccole modifiche al codice.

Cache_Lite è costituito da tre classi principali. La prima è la classe base Cache_Lite, che è responsabile solo della creazione e della lettura dei file della cache e non memorizza nel buffer l'output. Questa classe può essere utilizzata da sola nei casi in cui non è necessario utilizzare il buffering dell'output, ad esempio quando si salva il risultato dell'analisi di un modello PHP tramite uno script. Gli esempi qui mostrati non utilizzano direttamente la classe Cache_Lite e dimostrano l'uso delle altre due classi. Cache_Lite_Function viene utilizzato per chiamare una funzione o un metodo di classe e quindi memorizzare nella cache i risultati. Ciò può essere utile, ad esempio, per memorizzare nella cache il risultato di una query in My SQL?. La classe Cache_Lite_Output utilizza le funzioni di controllo dell'output PHP per intercettare i dati generati da uno script e archiviarli nei file di cache. Ciò consente di eseguire le stesse attività della soluzione precedente.

Ecco un esempio che ti mostrerà come utilizzare Cache_Lite per eseguire l'attività trattata nella parte precedente. Per considerare qualsiasi utilizzo di Cache_Lite, dobbiamo prima configurarlo - creare un array di parametri - che determinerà il comportamento della classe. Li esamineremo più in dettaglio di seguito, ma per ora tieni presente che il tuo script deve avere permessi di lettura e scrittura sulla directory cacheDir.

Esempio 5.7. 4.php (inizio)

// Collega la classe di output PEAR::Cache_Lite require_once "Cache/Lite/Output.php"; // Definisce le impostazioni per Cache_Lite$opzioni = array ( "cacheDir" => "./cache/" , "writeControl" => "true" , ​​"readControl" => "true" , ​​"readControlType" => "md5" ) ; // Crea un oggetto della classe Cache_Lite_Output

Per ogni parte dell'output dello script che desideri memorizzare nella cache, devi impostare la durata della cache in secondi. questa volta determina per quanto tempo recuperare i dati dalla cache. Trascorso questo tempo, i dati nel file verranno aggiornati. Successivamente, chiamiamo il metodo start(), disponibile solo nella classe Cahce_Lite_Output, che abilita il buffering dell'output. Passiamo 2 parametri al metodo: il primo è l'identificatore del file di cache, il secondo è il gruppo (tipo di cache). Il parametro "gruppo" consente di combinare diversi modelli, ciò consente di eseguire azioni di gruppo, ad esempio eliminando tutti i file di cache in un gruppo. Una volta terminato l'output della parte di cui abbiamo bisogno, dobbiamo chiamare il metodo stop(). Questo metodo interromperà il buffering e salverà il contenuto del buffer in un file.

Esempio 5.8. 4.php (continua)

// Imposta la durata della cache per questa parte$cache ->setLifeTime (604800); // Avvia il buffering per la sezione denominata header // e inserirlo nel gruppo Statico if (!$cache ->start ("header" , "Static") ) ( ?>"-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> "http://www.w3.org/1999/xhtml"> PEAR::Cache_Lite esempio "testo/html; set di caratteri=windows-1251" />

PEAR::Cache_Lite esempio

Orario di creazione dell'intestazione:
// Interrompe il buffering e scrive il buffer in un file$cache ->end(); )

La memorizzazione nella cache del corpo principale dell'output (corpo) e della parte inferiore (piè di pagina) è simile alla memorizzazione nella cache dell'intestazione. Tieni presente che impostiamo nuovamente la durata della cache per ogni parte successiva.

Esempio 5.9. 4.php (continua)

$cache ->setLifeTime (5); if (!$cache ->start ("body", "Dynamic")) ( echo "Tempo di creazione del corpo:". data ("H:i:s" ). "
" ; $cache ->end () ; ) $cache ->setLifeTime (604800) ; if (!$cache ->start ("footer" , "Static" ) ) ( ?> Ora di creazione finale:
FINE(); )

Quando richiami questa pagina per visualizzarla, Cache_Lite creerà i seguenti file nella directory della cache:

./cache/cache_Static_header ./cache/cache_Dynamic_body ./cache/cache_Static_footer

Se richiedi la stessa pagina in un secondo momento, il codice sopra ti mostrerà il contenuto di questi file, ovviamente, se la loro durata non è ancora scaduta.

  • Proteggi i file memorizzati nella cache.
  • Assicurati che la directory in cui memorizzi i file della cache non sia accessibile pubblicamente. in caso contrario, i visitatori del tuo sito saranno in grado di fare più di quanto vorresti che facessero.

Impostazioni Cache_Lite

Quando si chiama Cache_Lite (o una qualsiasi delle sue sottoclassi, come Cache_Lite_Output), esistono molti modi per controllarne il comportamento. Tutti i parametri devono essere inseriti in un array e passati al costruttore:

Esempio 5.10. 4.php (fine)

// Configura le impostazioni per Cache_Lite$opzioni = array ( "cacheDir" => "./cache/" , "writeControl" => TRUE , "readControl" => TRUE , "readControlType" => "md5" ) ; // Crea un oggetto Cache_Lite_Output$cache = nuovo Cache_Lite_Output($opzioni) ;

Nella versione attuale della classe (1.1), sono disponibili le seguenti impostazioni:

  • cacheDir: questa è la directory in cui verranno posizionati i file della cache. Il valore predefinito è la directory in cui viene eseguito lo script.
  • caching: questa opzione abilita o disabilita le funzionalità Cache_Lite. Ad esempio, se hai molte richieste a Cache_Lite e durante il debug desideri disattivare la memorizzazione nella cache, impostala su FALSE. Il valore predefinito è VERO.
  • durata: questo parametro contiene la durata della cache predefinita (in secondi). È possibile modificare il valore chiamando il metodo setLifeTime(). Il valore predefinito è 3600 (un'ora).
  • fileNameProtection – Se questa opzione è abilitata, Chache_Lite utilizzerà la codifica MD5 per generare il nome del file di cache. Ciò consente di utilizzare qualsiasi carattere nei nomi dei file e dei gruppi della cache, anche quelli vietati dal file system. Questa impostazione deve essere abilitata quando si utilizza Cache_Lite_Function. Il valore predefinito è TRUE (abilitato).
  • fileLocking – Questo parametro abilita i meccanismi per bloccare un file di cache mentre i dati vengono scritti su di esso. Il valore predefinito è TRUE (abilitato).
  • writeControl – Verifica che il file di cache sia stato scritto correttamente immediatamente al termine della scrittura. In caso di errore, lancia PEAR:Error. Questa funzionalità consente allo script di sovrascrivere nuovamente il file di cache, ma lo rallenta. Il valore predefinito è TRUE (abilitato).
  • readControl – Prima di leggere un file di cache, ne controlla la corruzione. Cache_Lite inserisce un valore di lunghezza nel file che può essere utilizzato per monitorarne l'integrità. Esiste anche un meccanismo alternativo per verificare l'integrità dei file. È abilitato dal parametro readControlType. Questi meccanismi rallentano leggermente la velocità, ma aiutano a garantire che i tuoi utenti visualizzino una pagina incorrotta. il valore predefinito è TRUE (abilitato).
  • readControlType: questo parametro determina il tipo di meccanismo di lettura del file di cache. Meccanismi disponibili: controllo di ridondanza ciclico ("crc32" - valore predefinito) - utilizza la funzione PHP crc32, hash "MD5" - utilizza la funzione PHP md5, o un semplice controllo della lunghezza - "strlen". Tieni presente che questo meccanismo non è destinato a proteggere i file della cache dall'accesso diretto da parte di utenti non autorizzati. Questo è solo un modo per determinare se un file è danneggiato o meno.

PearErrorMode – Abilita il metodo PEAR per la restituzione degli errori. Il valore predefinito è CACHE_LITE_PEAR_RETURN - restituisce l'oggetto /#c#?PEAR::Error.

  • memoryCaching – Se questa opzione è abilitata, ogni volta che si chiama la cache per scrivere su un file, questo viene scritto nell'array Cache_Lite. saveMemoryCachingState e getMemoryCachingState vengono utilizzati per accedere alla cache archiviata in memoria tra le richieste. Il vantaggio di questo metodo è che il contenuto della cache può essere archiviato in un singolo file, riducendo il numero di cicli di lettura/scrittura del disco. La cache viene ripristinata direttamente in un array a cui può accedere lo script. Nei nostri esempi utilizzeremo il consueto meccanismo Cache_Lite, ma potresti voler sperimentare questa opzione in seguito se hai un sito molto grande. L'impostazione predefinita è TRUE (disabilitato).
  • onlyMemoryCaching – Se abiliti questa opzione, verrà utilizzato solo il meccanismo di memorizzazione nella cache in memoria. L'impostazione predefinita è TRUE (disabilitato).

memoryCachingLimit – Questo parametro specifica il limite del numero di file di cache che possono essere archiviati in un array in memoria. Maggiore è il numero di file, maggiore sarà la quantità di memoria consumata. Pertanto, definire un limite è un’ottima idea. Naturalmente, ciò non influisce sulla dimensione del file di cache, poiché uno o due file di grandi dimensioni non creeranno alcun problema. il valore predefinito è 1000.

Svuotamento della cache

Cahce_Lite contiene un meccanismo efficace per determinare la durata dei file di cache, che crea una buona base per la sicurezza dei file e il loro aggiornamento tempestivo. Tuttavia, ci sono momenti in cui è necessario aggiornare immediatamente il file della cache. Per questi casi, esistono i metodi delete() e clean(). Il metodo Remove() è progettato per rimuovere un file di cache specifico. richiede l'ID della cache e il nome del gruppo a cui appartiene il file. L'esempio seguente eliminerà il file della cache del corpo dall'esempio precedente:

$cache ->rimuovi ("corpo", "Dinamico");

Il metodo clean() ci consente di eliminare tutti i file nella nostra directory se lo chiamiamo senza parametri. Se passi il nome del gruppo come parametro, tutti i file inclusi in questo gruppo verranno eliminati. Se volessimo rimuovere l'intestazione e la parte inferiore, allora dovremo inviare comandi simili a questi:

$cache ->clean ("Statico");

I metodi move() e clean() ovviamente devono essere richiamati in risposta ad eventi all'interno dell'applicazione. Ad esempio, se hai un forum, probabilmente dovresti eliminare il file di cache se un utente pubblica un nuovo messaggio. Sebbene questa soluzione sembri interessante, potrebbe comportare alcune modifiche al codice. Se disponi di uno script principale che si collega a ogni pagina dell'applicazione che un visitatore potrebbe visualizzare, puoi semplicemente controllare gli eventi in arrivo, come la variabile $_GET["newPost"], rimuovendo i file di cache richiesti. Ciò ti consentirà di creare un meccanismo di gestione della cache centralizzato. potresti anche includere questo codice in php.ini (vedi la descrizione dell'impostazione auto_prepend_file).

Chiamate di funzioni di memorizzazione nella cache

Nel Capitolo 2, XML, abbiamo esaminato l'accesso remoto ai servizi Web utilizzando SOAP e XML-RPC. Poiché i servizi Web sono accessibili tramite la rete, spesso è una buona idea memorizzare nella cache il risultato in modo che possa essere eseguito localmente anziché eseguire ripetutamente la stessa query lenta. Nel caso più semplice potremmo utilizzare le sessioni PHP, di cui abbiamo parlato in quel capitolo, ma poiché questa soluzione si basa sulla frequenza dei visitatori, l'apertura di una richiesta per ciascun visitatore sarebbe comunque lenta. In questi casi, Cache_Lite può essere molto utile.

  • PEAR utilizza Cache_Lite
  • Il programma di installazione Web PEAR (leggere l'Appendice D, utilizzo di PEAR) utilizza Cache_Lite per memorizzare nella cache le richieste XML-RPC inviate al server Web PEAR.

Nella sezione chiamata “Come posso utilizzare i servizi Web SOAP con PHP?”, abbiamo scritto un client per servire un servizio Web SOAP in base al suo file WSDL; Questo servizio fornisce informazioni meteorologiche a tutti gli aeroporti del mondo. Ecco il codice che riceve i dati dal server remoto:

$paesi = $stationInfo ->listCountries () ;

$paese = $stationInfo ->searchByCountry ($_GET ["paese"]) ;

In entrambi i casi queste chiamate corrispondono ad una richiesta di dati sulla rete. Utilizzando Cache_Lite, potremmo memorizzare nella cache i dati restituiti dal servizio ed essere in grado di riutilizzarli. Ciò eviterebbe ulteriori connessioni di rete non necessarie e aumenterebbe significativamente la velocità di esecuzione. Tieni presente che qui stiamo esaminando solo il codice relativo al nostro argomento. Per prima cosa abilitiamo Cache_Lite_Function:

Esempio 5.11. 5.php (inizio)

// Include PEAR::Cache_Lite_Function require_once "Cache/Lite/Function.php";

Esempio 5.12. 5.php (continua)

// Imposta i parametri per Cache_Lite_Function // ATTENZIONE: fileNameProtection = TRUE!$opzioni = array ( "cacheDir" => "./cache/" , "fileNameProtection" => TRUE , "writeControl" => TRUE , "readControl" => TRUE , "readControlType" => "strlen" , "defaultGroup" => "SAPONE" ) ; // Crea un oggetto della classe Cache_Lite_Function$cache = nuova Cache_Lite_Function($opzioni) ;

È importante che il parametro fileNameProtection sia impostato su TRUE. Questo è il valore predefinito, ma l'ho impostato manualmente specificatamente per enfatizzarne il significato. L'impostazione di questa opzione su FALSE risulterà in un nome file non valido, quindi la memorizzazione nella cache non verrà eseguita.

Esempio 5.13. 5.php (continua)

$paesi = $cache ->chiamata ("stationInfo->listCountries");

Esempio 5.14. 5.php (fine)

$paese = $cache ->chiama ( "stationInfo->searchByCountry",$_GET ["paese"]) ;

Se viene effettuata una richiesta per la prima volta, Cache_Lite_Function memorizza i risultati come un array serializzato in un file di cache (non devi preoccuparti di questo) e questo file verrà utilizzato per richieste future fino alla scadenza della sua durata. setLifeTime può essere utilizzato per determinare per quanto tempo vivrà un file di cache prima di aggiornarne le informazioni. Il valore predefinito è 1 ora (3600 secondi).

In generale, Cache_Lite fornisce un unico sistema facile da usare per risolvere qualsiasi problema relativo alla memorizzazione nella cache. Dato che il livello successivo sono i siti con un traffico particolarmente elevato, dovresti esplorare PEAR::Cache, che è il fratello maggiore di Cache_Lite. Fornisce inoltre funzionalità di caching avanzate, come la memorizzazione nella cache della memoria condivisa come alternativa alla memorizzazione nella cache dei file, o l'estensione Msession PHP per aiutare a memorizzare i dati in una sessione bilanciata, che è particolarmente utile nei server WEB bilanciati. Fornirò altro materiale su PEAR::Cache alla fine di questo articolo. Cache_Lite, tuttavia, offre funzionalità più che sufficienti e soddisfa le esigenze della maggior parte dei siti.

Come posso gestire la memorizzazione nella cache lato client utilizzando PHP?

Ora che abbiamo esaminato le opzioni per sovrascrivere la cache lato client e come può essere implementata la cache lato client, è tempo di esaminare un meccanismo che ci consentirà di controllare la cache lato client utilizzando PHP. Questo approccio funzionerà solo se utilizzi PHP con un server Apache, poiché utilizzeremo la funzione getallheaders per ottenere le intestazioni inviate dal browser. questa funzione funziona solo in Apache.

Nuovi nomi di funzioni

Se utilizzi PHP 4.3.0 con Apache, le intestazioni HTTP sono disponibili tramite le funzioni apache_request_headers e apache_response_headers. La funzione getallheaders è diventata un alias per la nuova funzione apache_request_headers.

Il meccanismo per lavorare con la cache del browser web è ancora una volta HTTP. Molte intestazioni sono coinvolte nell'istruzione ai browser Web e ai server proxy di memorizzare nella cache una pagina in modo indipendente, una situazione complicata dal fatto che alcuni di essi sono disponibili solo con HTTP 1.1.

Controllo delle intestazioni HTTP nel tuo browser

Uno strumento semplice ma molto conveniente per controllare le intestazioni di richiesta e risposta è Live Http Headers? – componente aggiuntivo per il browser Mozilla. È importante sapere esattamente quali intestazioni sta inviando il tuo script, soprattutto quando hai a che fare con le intestazioni della memorizzazione nella cache HTTP.

Per semplicità, prenderemo in considerazione solo le intestazioni della cache HTTP 1.0, ovvero Expires, Last-Modified e If-Modified-Since, nonché il codice di stato HTTP 304 (Not Modified).

Altri header disponibili con HTTP 1.1, come Cache-Control ed ETag, hanno lo scopo di fornire un meccanismo avanzato che può essere utilizzato insieme allo stato della sessione web, in altre parole, la versione di una determinata pagina visualizzata a un visitatore non autorizzato potrebbe essere significativamente diverso da quello visualizzato da un utente autorizzato. Le intestazioni HTTP 1.1 sono state originariamente aggiunte per consentire la memorizzazione nella cache di tali pagine.

Scadenza della durata della pagina

L'intestazione più semplice da utilizzare è l'intestazione Expire, che imposta una data (possibilmente futura) in cui la pagina scadrà. Fino a questo punto, al browser Web è consentito utilizzare la versione memorizzata nella cache della pagina.

Esempio 5.15. 6.php

/** * Invia l'intestazione HTTP 1.0 Expires. * @param int numero di secondi rimanenti fino alla scadenza del tempo */ funzione setExpires($scadenza) ( intestazione ("Scadenza: " . gmdate ("D, d M Y H:i:s" , ora () + $scadenza ). "GMT" ) ; ) // Imposta l'intestazione della data di scadenza Expires setExpires(10) ; // Visualizza l'eco "Questa pagina si autodistruggerà tra 10 secondi
"
; eco "Adesso". gmdate("H:i:s") . " GMT
" ; echo """>Visualizza di nuovo
" ;

La funzione setExpires invia un'intestazione HTTP Expires con un tempo futuro specificato in secondi. L'esempio sopra mostra l'ora GMT corrente e visualizza un collegamento che ti consente di tornare alla pagina. Utilizzando il pulsante Aggiorna del tuo browser, puoi dire al browser che desideri aggiornare la sua cache. Utilizzando il collegamento vedrai che l'ora cambia solo una volta ogni 10 secondi.

Date e orari in HTTP

Le date in HTTP vengono sempre calcolate rispetto al Greenwich Mean Time (GMT). La funzione PHP gmdate è esattamente la stessa funzione di date, tranne per il fatto che compensa automaticamente l'ora GMT in base all'orologio di sistema e alle impostazioni della regione del server.

Quando il browser incontra l'intestazione Expires, memorizza la pagina nella cache. Tutte le richieste successive per la pagina effettuate prima della scadenza specificata utilizzano la versione memorizzata nella cache della pagina e non viene effettuata alcuna richiesta al server web.

L'intestazione Expires è per lo più semplice da implementare, ma nella maggior parte dei casi, a meno che tu non sia una persona altamente organizzata, non hai modo di sapere esattamente quando viene aggiornata una determinata pagina del tuo sito. Poiché il browser contatterà il server solo dopo che la pagina è diventata obsoleta, non c'è modo di dire al browser che una pagina nella sua cache è obsoleta. Perdi anche parte del traffico verso il tuo sito web perché il browser non contatta il server quando richiede una pagina memorizzata nella cache.

Orario cambio pagina

È più pratico utilizzare le intestazioni Last-Modified e If-Modified-Since disponibili in HTTP 1.0. Tecnicamente nota come richiesta GET condizionale, restituisci qualsiasi contenuto in base alla condizione dell'intestazione della richiesta If-Modified-Since.

Quando utilizzi questo metodo, devi inviare un'intestazione Last-Modified ogni volta che si accede allo script PHP. La prossima volta che il browser richiede la pagina, invierà un'intestazione If-Modified-Since contenente il tempo che lo script può utilizzare per determinare se la pagina è stata aggiornata dall'ultima richiesta. In caso contrario, lo script invia un codice di stato HTTP 304 per indicare che la pagina non è cambiata, senza stampare il contenuto della pagina.

L'esempio più semplice di GET condizionale è piuttosto complicato, uno strumento abbastanza conveniente per mostrare come funziona è PEAR::Cache_Lite. Tuttavia, questo non deve essere considerato un esempio di caching del server; implica semplicemente che un file venga periodicamente modificato.

Esempio 5.16. 7.php (inizio)

// Connetti PEAR::Cache_Lite require_once "Cache/Lite.php"; // Definisce le impostazioni di Cache_Lite$opzioni = array ( "cacheDir" => "./cache/" ) ; // Inizializza Cache_Lite$cache = nuova Cache_Lite($opzioni) ; // Alcuni dati fittizi da memorizzare$id = "MyCache"; // Inizializza la cache se la pagina viene richiesta per la prima volta if (!$cache ->get ($id)) ($cache ->save ("Dummy", $id) ;) // Randomizzatore...$casuale = matrice (0, 1, 1); casuale ($random); // Aggiornamento casuale della cache if ($random [ 0 ] == 0 ) ( $cache -> salva ("Dummy", $id) ;) // Ottiene l'ora dell'ultima modifica del file di cache$lastModified = filemtime ($cache ->_file) ; intestazione ("Ultima modifica: " . gmdate ("D, d M Y H:i:s" , $lastModified ). " GMT" ) ; < v6 отдаёт их неправильно) $modificatoSince = 0; ) se ($lastModified<= $modifiedSince ) { header ("HTTP/1.1 304 Not Modified" ) ; exit () ; } echo "Сейчас " . gmdate ("H:i:s" ) . "GMT
"
; echo """>Aggiorna
" ;

Ricordarsi di utilizzare il collegamento Aggiorna durante l'esecuzione di questo esempio (facendo clic su Aggiorna in genere si svuota la cache del browser). Se fai clic ripetutamente sul collegamento, alla fine la cache verrà modificata, il tuo browser rimuoverà la versione dalla cache e memorizzerà al suo interno la nuova pagina fornita da PHP.

Nell'esempio sopra, abbiamo utilizzato PEAR::Cache_Lite per creare un file di cache modificato in modo casuale. Impostiamo l'orario di modifica del file cache con questa riga:

$lastModified = filemtime ($cache ->_file) ;

Tecnicamente parlando, questo è un hack perché la variabile $_file della classe PEAR::Cache_Lite dovrebbe essere privata. Tuttavia, siamo costretti a utilizzarlo per ottenere il nome del file di cache e scoprire l'ora della sua modifica.

Quindi, utilizzando l'ora di modifica del file di cache, inviamo l'intestazione Last-Modified. Dobbiamo inviarlo per ogni pagina servita per forzare il browser a inviarci un'intestazione If-Modified-Since con ogni richiesta.

// Emette l'intestazione HTTP Last-Modified intestazione ("Ultima modifica: " . gmdate ("D, d M Y H:i:s" , $lastModified ). " GMT" ) ;

L'utilizzo della funzione getallheaders garantisce di ottenere tutte le intestazioni in entrata da PHP come array. Dobbiamo quindi verificare che l'intestazione If-Modified-Since esista effettivamente, se esiste, dobbiamo gestire il caso speciale delle versioni precedenti di Mozilla (inferiori alla versione 6) che aggiungevano un campo aggiuntivo all'intestazione If-Modified- in la fine (che si discosta dalle specifiche). Utilizzando la funzione PHP strtotime, otteniamo il timestamp della data passataci dal browser. Se non è presente tale intestazione, assegniamo un timestamp pari a zero, costringendo così PHP a fornire al visitatore l'ultima versione della pagina.

// Ottieni le intestazioni delle richieste del client - solo Apache$richiesta = getallheaders(); if (isset ($request ["Se-Modificato-Since"])) ( // Dividi se modificato dal (Netscape< v6 отдаёт их неправильно) $modificatoSince = esplode (";" , $request [ "Se-Modificato-Since" ] ); // Converte la richiesta If-Modified-Since del client in un timestamp$ modificatoSince = strtotime ($ modificatoSince [0]); ) altro ( // Imposta il tempo di modifica su zero$modificatoSince = 0; )

Infine, controlliamo se la cache è stata modificata dall'ultima volta che il visitatore ha ricevuto questa pagina. In caso contrario, inviamo semplicemente una risposta Not Modified nell'intestazione e interrompiamo l'esecuzione dello script, senza caricare il collegamento dati e risparmiando tempo della CPU istruendo il browser a visualizzare una versione della pagina memorizzata nella cache.

// Confronta l'ora dell'ultima modifica del contenuto con la cache del client if ($ultimoModificato<= $modifiedSince ) { // Scarica il canale di trasmissione dati! header("HTTP/1.1 304 non modificato"); Uscita(); )

Se combini l'approccio relativo all'ora dell'ultima modifica con un valore temporale già disponibile nella tua applicazione (ad esempio, l'ora dell'articolo di notizie più recente o l'ora di scadenza dal sistema di memorizzazione nella cache lato server che abbiamo visto nell'ultima soluzione) , puoi sfruttare la cache del browser web e alleggerire il collegamento dati, ove possibile risparmiando traffico informativo dal tuo sito e migliorandone la performance percepita.

Fai attenzione quando testi la memorizzazione nella cache eseguita con questo stile; se lo fai in modo errato, potresti far sì che i tuoi visitatori abbiano sempre copie obsolete del tuo sito.

Collegamenti aggiuntivi

  • Richiesta GET con condizione (GET condizionale)
  • Tracciamento dei contenuti su siti dinamici

I migliori articoli sull'argomento