Cum se configurează smartphone-uri și PC-uri. Portal informativ
  • Acasă
  • Programe
  • Memorarea în cache în PHP. Metode pentru stocarea în cache a datelor în PHP

Memorarea în cache în PHP. Metode pentru stocarea în cache a datelor în PHP


stocarea în cache în PHP

Pe vremuri bune, când crearea de site-uri web era la fel de simplă ca și tastarea câtorva pagini HTML, trimiterea paginilor web către browser era o chestiune simplă de trimitere de fișiere de către serverul web. Vizitatorii site-ului puteau vedea aceste pagini mici, doar text, aproape instantaneu (cu excepția utilizatorilor modemurilor lente). Odată ce pagina a fost încărcată, browserul o memorează în cache undeva pe computerul local, astfel încât, dacă pagina este solicitată din nou, să poată prelua versiunea locală din cache, trimițând doar o scurtă solicitare pentru a se asigura că pagina de pe server nu are fost modificată. Cererile au fost procesate rapid și cel mai eficient și toată lumea a fost mulțumită (cu excepția celor care foloseau modemuri de 9600 baud).

Apariția paginilor web dinamice a schimbat lucrurile în rău, rupând efectiv acest model de servire a paginilor web din cauza a două probleme:

1. Când serverul primește o solicitare pentru o pagină web dinamică, se efectuează unele procesări intermediare, de exemplu, analizarea scriptului de către motorul PHP, care trebuie finalizată. Acest lucru ne oferă o întârziere înainte ca serverul web să înceapă să trimită rezultate către browser. Pentru un script PHP simplu, acest lucru nu este semnificativ, dar în cazul unei aplicații mai complexe, motorul PHP poate efectua multe acțiuni înainte ca pagina să fie gata pentru a fi trimisă. Acești pași suplimentari au ca rezultat o întârziere vizibilă între solicitările utilizatorilor și paginile care sunt afișate efectiv în browserele lor.

2. Un server web obișnuit, cum ar fi Apache, folosește timpul de modificare a fișierelor pentru a comunica corect browserului starea cache a paginii solicitate. În site-urile web dinamice, script-ul PHP în sine se poate schimba doar ocazional, în timp ce conținutul pe care îl afișează, eventual rezident într-o bază de date, se modifică frecvent. Serverul web nu are de unde să știe despre modificările aduse bazei de date, așa că nu trimite data ultimei modificări. În cazul în care clientul (browserul) nu primește nicio indicație despre cât timp datele sunt corecte, presupune că va trebui să solicite o nouă pagină data viitoare. Serverul web va răspunde întotdeauna cu o versiune actualizată a paginii, indiferent dacă datele s-au modificat. Pentru a evita acest neajuns, majoritatea dezvoltatorilor web folosesc metaetichete sau anteturi HTTP pentru a instrui browserul să nu folosească niciodată versiunea stocată în cache a paginii. Cu toate acestea, acest lucru anulează capacitatea naturală a browserului web de a stoca în cache paginile web și are unele dezavantaje semnificative. De exemplu, conținutul unei pagini dinamice se poate schimba o dată pe zi, astfel că beneficiul obținut de a avea browserul în cachea paginii chiar și pentru 24 de ore este evident.

De obicei, pentru aplicațiile PHP mici este destul de posibil să ignorați existența acestor probleme, dar pe măsură ce complexitatea și traficul site-ului dvs. cresc, puteți întâmpina probleme. Cu toate acestea, ambele probleme pot fi rezolvate: prima prin memorarea în cache pe server, a doua prin gestionarea stocării în cache pe partea client din aplicația dvs. Abordarea pe care o luați va depinde de nevoile dumneavoastră specifice, dar în acest articol vă vom arăta cum puteți rezolva ambele probleme folosind PHP și unele clase de bibliotecă PEAR.

cum pot împiedica browserele să memoreze o pagină în cache?

Înainte de a ne uita la tehnicile de stocare în cache pentru client și server, trebuie mai întâi să înțelegem cum să împiedicăm browserul web (și serverele proxy) să memoreze paginile în cache. Principala modalitate de a realiza acest lucru este utilizarea metaetichetelor HTML:

Prin inserarea unei date trecute în metaeticheta Expires, îi spuneți browserului că copia stocată în cache a paginii este întotdeauna învechită. Aceasta înseamnă că browserul nu ar trebui să memoreze pagina în cache. Meta tag Pragma: no-cache este o convenție destul de bine acceptată pe care o urmează majoritatea browserelor web. Odată ce detectează această etichetă, de obicei nu pun în cache pagina (deși nu există nicio garanție, aceasta este doar o convenție). Sună bine, dar există două probleme cu utilizarea metaetichetelor:

1. Dacă eticheta nu a existat atunci când pagina a fost solicitată prima dată de browser, dar apare mai târziu (de exemplu, ați modificat fișierul de includere pageheader.php care este antetul fiecărei pagini web), browserul va rămâne fără cunoștință și utilizați copia sa în cache a originalului.

2. Serverele proxy care memorează în cache paginile web nu vor examina deloc direct conținutul documentului HTML. În schimb, se bazează doar pe serverul web de la care provin documentele și pe protocolul HTTP. Cu alte cuvinte, browserul poate crede că nu ar trebui să memoreze pagina în cache, dar proxy-ul dintre browser și serverul web probabil că nu știe acest lucru - și va continua să trimită aceeași pagină către client.

O abordare mai bună este să utilizați protocolul HTTP direct folosind funcția de antet PHP:


header("Pragma: fără cache");
?>

Putem face un pas mai departe utilizând antetul Cache-Control, care este compatibil cu browserele care acceptă HTTP 1.1:

header(„Expiră: Luni, 26 iulie 1997 05:00:00 GMT”);
header("Controlul cache: fără stocare, fără cache, revalidare obligatorie");
header("Controlul cache: post-verificare=0, pre-verificare=0", FALSE);
header("Pragma: fără cache");
?>

Acest lucru asigură că niciun browser web sau server proxy intermediar nu memorează pagina în cache, astfel încât vizitatorii primesc întotdeauna cea mai actualizată versiune a conținutului. De fapt, primul antet ar trebui să fie autonom, acesta este cel mai bun mod de a vă asigura că pagina nu este stocată în cache. Anteturile Cache-Control și Pragma sunt adăugate din motive de siguranță. Deși nu funcționează în toate browserele sau proxy-urile, vor surprinde unele cazuri în care Expira nu funcționează conform așteptărilor (de exemplu, dacă data de pe computerul clientului nu este setată corect). Desigur, evitarea stocării în cache ne prezintă în totalitate problemele pe care le-am discutat la începutul acestui capitol. Acum ne vom uita la rezolvarea acestor probleme.

Internet Explorer și descărcarea fișierelor în cache

Pot apărea probleme atunci când aveți de-a face cu stocarea în cache și descărcarea fișierelor. Dacă, la deservirea unui fișier descărcat printr-un script PHP, sunt folosite anteturi precum Content-Disposition: attachment, filename=myFile.pdf sau Content-Disposition: inline, filename=myFile.pdf, veți avea probleme cu Internet Explorer dacă spuneți browserului să nu memoreze pagina în cache.

Internet Explorer gestionează descărcările într-un mod destul de neobișnuit, făcând două solicitări către site. Prima solicitare descarcă fișierul și îl stochează în cache până când se face a doua solicitare (fără a stoca răspunsul). Această solicitare face ca fișierul să fie transferat către utilizatorul final în funcție de tipul de fișier (de exemplu, lansează Acrobat Reader dacă fișierul este un document PDF). Aceasta înseamnă că, dacă trimiteți anteturi care împiedică browserul să memoreze pagina în cache, Internet Explorer va șterge fișierul între prima și a doua solicitare, rezultând nimic pentru utilizatorul final. Dacă fișierul pe care îl serviți ca script PHP nu se modifică, una dintre cele mai simple soluții este să eliminați anteturile „inhibarea caching-ului” din script.

Dacă fișierul descărcat se modifică în mod regulat (adică doriți ca browserul să descarce cea mai nouă versiune), ar trebui să utilizați antetul Ultima modificare și să vă asigurați că timpul de modificare dintre două solicitări consecutive nu se modifică. Trebuie să faceți acest lucru într-un mod care să nu afecteze utilizatorii browserelor care gestionează corect descărcările. O soluție în acest caz ar fi să stocați fișierul pe serverul dvs. web și să furnizați un link simplu către acesta, permițând serverului web să vă raporteze anteturile de cache. Desigur, această soluție poate să nu fie acceptabilă dacă se presupune accesul autorizat la fișier, deoarece permite încărcarea directă a fișierului stocat.

cum pot captura date de pe server pentru stocare în cache?

Este timpul să ne uităm la modul în care putem reduce latența utilizând stocarea în cache a ieșirilor de pe partea serverului. Deci, puteți servi pagina ca de obicei, rulând interogări în baza de date și așa mai departe în PHP. Dar înainte de a trimite rezultatul către browser, îl captăm și salvăm pagina finalizată, de exemplu, într-un fișier. La următoarea solicitare, scriptul PHP verifică mai întâi o versiune în cache a paginii. Dacă există, scriptul trimite versiunea în cache la browser, eliminând astfel întârzierea re-creării paginii.

Câteva cuvinte despre stocarea în cache folosind șabloane. Prezența motoarelor de șabloane precum Smarty vorbește adesea despre stocarea în cache a șabloanelor. De obicei, aceste motoare oferă un mecanism încorporat pentru salvarea unei versiuni compilate a șablonului (adică, generarea sursei PHP din șablon), ceea ce ne împiedică să analizăm șablonul de fiecare dată când este solicitată o pagină. Acest lucru nu trebuie confundat cu stocarea în cache a ieșirii, care se referă la stocarea în cache a HTML-ului furnizat (sau a altor rezultate) pe care PHP o trimite către browser. Puteți utiliza cu succes ambele tipuri de stocare în cache simultan pe același site.

Ne vom uita acum la mecanismul de stocare în cache încorporat al PHP care utilizează buffering de ieșire, pe care îl puteți utiliza indiferent de modul în care vă creați conținutul (cu sau fără șabloane). Luați în considerare o situație în care scriptul dvs. afișează rezultatul, folosind, de exemplu, ecou sau print pentru a scoate date direct în browser. Într-un astfel de caz, puteți utiliza funcțiile de control de ieșire ale PHP pentru a stoca date în memoria tampon asupra căreia scriptul dumneavoastră PHP are control.
Iată un exemplu simplu:


ob_start();
// Afișează un text (care este salvat în buffer);
echo „1. Trimiteți acest lucru în buffer
";
// Obține conținutul bufferului
$buffer = ob_get_contents();
// Opriți stocarea tampon și ștergeți tamponul de ieșire
ob_end_clean();
// Afișează un text ca de obicei
ecou „2. Ieșire normală
";
// Imprimați conținutul tamponului
echo $buffer;
?>

Buffer-ul în sine stochează ieșirea ca șir. Deci, în scriptul de mai sus, începem să punem în buffer cu ob_start și să folosim echo pentru a scoate ceva. Apoi folosim ob_get_contents pentru a prelua datele stocate în tampon de instrucțiunea echo și le stocăm într-un șir. Funcția ob_end_clean oprește stocarea tampon de ieșire și îi distruge conținutul. Alternativ, puteți utiliza ob_end_flush pentru a imprima conținutul bufferului. Scriptul de mai sus va scoate:

2. Ieșire normală
1. Trimiteți acest lucru în buffer

Cu alte cuvinte, am capturat rezultatul primului ecou, ​​apoi l-am trimis în browser după al doilea ecou. După cum puteți vedea din acest exemplu simplu, tamponarea de ieșire este un instrument foarte puternic pentru modelarea site-ului dvs., oferă o soluție de stocare în cache, așa cum vom vedea în curând și este o modalitate excelentă de a ascunde erorile de la vizitatorii site-ului dvs. De asemenea, oferă o opțiune alternativă pentru redirecționarea browserului în situații precum autentificarea utilizatorului.

Antete HTTP și buffering de ieșire

Bufferingul de ieșire poate ajuta la rezolvarea celei mai frecvente probleme cu funcția de antet, ca să nu mai vorbim de session_start și set_cookie. De obicei, dacă apelați oricare dintre aceste funcții după ce pagina a început redarea, veți primi un mesaj de eroare urât. Când tamponarea de ieșire este activată, singurul tip de ieșire care evită stocarea în tampon sunt anteturile HTTP. Folosind ob_start chiar la începutul execuției aplicației, puteți trimite anteturi în orice moment al programului care vă place, fără a întâmpina erorile obișnuite. Apoi, odată ce sunteți sigur că nu mai trebuie să imprimați alte anteturi HTTP, puteți imprima imediat conținutul paginii din buffer.

/* Trebuie remarcat faptul că o astfel de utilizare a acestei funcții este nejustificată. În cele mai multe cazuri, pur și simplu nu este nevoie să utilizați tamponarea de ieșire pentru a scăpa de erori de acest tip și totul poate fi corectat cu ușurință printr-un design adecvat al aplicației - aprox. traducator */

folosind tamponarea de ieșire pentru stocarea în cache pe partea serverului

Ați văzut deja un exemplu de bază de buffering de ieșire, acum următorul pas este în cazul în care tamponul este salvat într-un fișier:

// Dacă există o versiune în cache...
dacă (fișier_există("./cache/2.cache")) (
// Citiți și scoateți fișierul
readfile("./cache/2.cache");
Ieșire();
}
// Porniți ieșirea în buffer
ob_start();
// Afișează restul HTML-ului
?>
>http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
>http://www.w3.org/1999/xhtml">

Pagina stocată în cache

Această pagină este stocată în cache folosind PHP
Funcții>http://www.php.net/outcontrol">Funcții de control a ieșirii

// Obține conținutul bufferului
$buffer = ob_get_contents();
// Opriți stocarea tampon și scoateți bufferul
ob_end_flush();
// Salvarea unui fișier cache cu conținut
$fp = fopen("./cache/2.cache", "w");
fwrite($fp, $buffer);
fclose($fp);
?>

În primul rând, acest script verifică prezența unei versiuni a paginii în cache și, dacă aceasta există, scriptul o citește și o afișează. În caz contrar, folosește buffering de ieșire pentru a crea o versiune stocată în cache a paginii. După ce utilizați ob_end_flush pentru a afișa pagina utilizatorului, aceasta este salvată ca fișier.

blocarea tamponului

Într-o abordare simplificată, memorăm în cache tamponul de ieșire ca o singură pagină. Cu toate acestea, această abordare elimină funcționalitatea reală oferită de funcțiile de control de ieșire ale PHP.
Fără îndoială, unele părți ale paginii pe care le trimiteți vizitatorului dvs. se modifică foarte rar, cum ar fi antetul, meniul și subsolul. Cu toate acestea, alte părți, cum ar fi tabelele care conțin discuții pe forum, se pot schimba destul de frecvent. Buffer-ul de ieșire poate fi folosit pentru a stoca în cache secțiuni ale unei pagini în fișiere separate, apoi pentru a construi pagina din ele - o soluție care elimină nevoia de interogări repetate la baza de date, bucle while etc. Puteți atribui fiecărui bloc de pagină o dată de expirare după care fișierul cache este recreat sau, alternativ, puteți include un mecanism în aplicația dvs. care va șterge fișierul cache ori de câte ori conținutul stocat în acesta este modificat.
Iată un exemplu care demonstrează acest principiu:

/
* Scrieți fișierul cache
* Conținutul șirului @param – conținutul tamponului
* @param șir nume fișier – numele fișierului folosit la crearea fișierului cache
* @return nul
*/
funcția writeCache($conținut, $nume fișier) (
$fp = fopen("./cache/" . $nume fișier, "w");
fwrite($fp, $conținut);
fclose($fp);
}
* Verificarea fișierelor cache
* @param șir nume fișier – numele fișierului cache de verificat
* @param int expiry – „vârsta” maximă a fișierului în secunde
* @return conținuturi cache mixte sau false
*/
funcția readCache($filename, $expiry) (
dacă (fișier_există("./cache/" . $filename)) (
if ((time() - $expiry) >filemtime("./cache/" . $filename))
returnează FALSE;
$cache = fisier("./cache/" . $nume fisier);
return implode("", $cache);
}
returnează FALSE;
}
?>

Primele două funcții pe care le-am definit, writeCache și readCache, sunt folosite pentru a crea fișiere cache și, respectiv, a verifica existența acestora. Funcția writeCache ia ca argumente datele pentru cache și numele fișierului folosit pentru a crea fișierul cache. Funcția readCache primește numele fișierului cache și timpul în secunde după care fișierul cache ar trebui să fie considerat învechit. Dacă găsește fișierul cache valid, scriptul va returna conținutul său, în caz contrar va returna FALSE pentru a indica faptul că fișierul cache nu există sau este învechit.

În acest exemplu am folosit o abordare procedurală. Cu toate acestea, nu recomand să faceți acest lucru în practică, deoarece va ajunge într-un cod foarte dezordonat (vedeți soluțiile ulterioare pentru o alternativă mai bună) și va cauza probabil probleme de blocare a fișierelor (de exemplu, ce se întâmplă când cineva accesează memoria cache în timp ce acesta este în curs de actualizare?).
Să continuăm cu acest exemplu. Odată ce bufferingul de ieșire a început, începe procesarea. Scriptul apelează mai întâi readCache pentru a vedea dacă fișierul 3_header.cache există - conține antetul paginii, adică antetul HTML și începutul corpului. Folosim funcția de dată pentru a afișa ora la care pagina a fost generată efectiv, astfel încât veți vedea diferitele fișiere cache în acțiune atunci când pagina este redată.

// Porniți ieșirea în buffer
ob_start();
// Prelucrare antet
dacă (!$header = readCache ("3_header.cache", 604800)) (
// Ieșire antet
?>
>http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
>http://www.w3.org/1999/xhtml">

Pagina stocată în cache bloc cu bloc

Timp de creare a antetului:

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

Ce se întâmplă când fișierul cache nu este găsit? Un anumit conținut este scos și atribuit unei variabile folosind ob_get_contents, după care tamponul este șters de funcția ob_clean. Acest lucru ne permite să captăm ieșirea bucată cu bucată și să o potrivim cu fișierele cache individuale folosind writeCache. Titlul paginii este acum stocat ca un fișier care poate fi folosit fără intervenția noastră în reconstruirea paginii. Să ne întoarcem pentru o secundă la începutul declarației condiționale. Când am apelat readCache, i-am trecut o durată de viață cache de 604800 de secunde (o săptămână), readCache folosește timpul de modificare a fișierului cache pentru a determina dacă fișierul cache este încă valid.

Pentru conținutul (corpul) paginii vom folosi în continuare același proces. Cu toate acestea, de data aceasta când numim readCache vom folosi o durată de viață a cache-ului de cinci secunde, fișierul cache va fi modificat de fiecare dată când este „mai vechi” de 5 secunde:

// Procesează corpul paginii
dacă (!$body = readCache("3_body.cache", 5)) (
ecou „Timpul creării corpului: „ . data("H:i:s"). "
";
$body = ob_get_contents();
ob_clean();
writeCache($body, "3_body.cache");
}
?>

Subsolul poate fi modificat efectiv în același mod ca și antetul.
Rezultatul final arată cam așa:
- ora de creare a antetului - 17:10:42;
- timpul de creare a corpului - 18:07:40;
- timpul de creare a subsolului - 17:10:42.
Antetul și subsolul sunt actualizate săptămânal, în timp ce corpul este modificat când este mai vechi de 5 secunde.

tampon imbricate

Puteți imbrica un buffer într-un altul practic la nesfârșit, apelând ob_start în mod repetat. Acest lucru poate fi util dacă aveți o mulțime de operațiuni care folosesc bufferul de ieșire, de exemplu unele care captează mesaje de eroare PHP, altele care se ocupă de stocarea în cache. Trebuie să vă asigurați că ob_end_flush sau ob_end_clean este apelat de fiecare dată când este utilizat ob_start.

Cum pot implementa un sistem simplu de stocare în cache pe partea serverului?
Acum că înțelegem ideile din spatele stocării tampon de ieșire, este timpul să ne uităm la modul în care putem pune acest proces în acțiune într-un mod ușor de întreținut. Pentru a face acest lucru, vom folosi puțin ajutor de la PEAR::CacheLite.

După cum am spus, în interesul de a face codul mai ușor de întreținut și de a avea un mecanism de cache fiabil, este înțelept să atribuiți responsabilitatea pentru logica cache-ului claselor în care aveți încredere. Cache_Lite este o bibliotecă de stocare în cache puternică, dar ușor de utilizat, care se ocupă de sarcini precum blocarea temporară a fișierelor cache, crearea și validarea acestora, gestionarea buffer-ului de ieșire și stocarea directă în cache a rezultatului unei funcții sau unei metode de clasă. Motivul principal pentru alegerea acestei biblioteci este integrarea relativ simplă a lui Cache_Lite într-o aplicație existentă, care necesită doar modificări minore ale codului.

Cache_Lite constă din trei clase principale. Prima este clasa de bază Cache_Lite, care este responsabilă numai pentru crearea și citirea fișierelor cache și nu tamponează ieșirea. Această clasă poate fi utilizată singură în cazurile în care nu este nevoie să folosiți buffering de ieșire, cum ar fi atunci când salvați rezultatul analizării unui șablon printr-un script PHP. Exemplele prezentate aici nu folosesc clasa Cache_Lite direct și demonstrează utilizarea celorlalte două clase. Cache_Lite_Function este folosit pentru a apela o funcție sau o metodă de clasă și apoi pentru a stoca în cache rezultatele. Acest lucru poate fi util, de exemplu, pentru memorarea în cache a rezultatului unei interogări MySQL. Clasa Cache_Lite_Output folosește funcțiile de control de ieșire ale PHP pentru a intercepta datele generate de un script și a le stoca în fișiere cache. Acest lucru vă permite să efectuați aceleași sarcini ca soluția anterioară.

Setări Cache_Lite

În versiunea curentă a clasei (1.1), sunt disponibile următoarele setări:
- cacheDir - directorul în care vor fi plasate fișierele cache. Valoarea implicită este directorul în care este executat scriptul;
- cache - această opțiune activează sau dezactivează capabilitățile Cache_Lite. De exemplu, dacă aveți o mulțime de solicitări către Cache_Lite și în timpul depanării doriți să dezactivați stocarea în cache, setați-o la FALSE. Valoarea implicită este TRUE.
durata de viață - parametrul conține durata de viață implicită a cache-ului (în secunde);
- fileNameProtection - utilizați codarea MD5 pentru a genera un nume de fișier cache. Acest lucru vă permite să utilizați orice caractere în numele fișierelor și grupurilor cache, chiar și cele interzise de sistemul de fișiere;
- fileLocking - activează mecanismele de blocare a unui fișier cu un cache în timp ce datele sunt scrise în el;
- writeControl - verifică dacă fișierul cache a fost scris corect imediat după terminarea scrierii;
- readControl - înainte de a citi un fișier cache, îl verifică pentru distorsiuni;
- readControlType - acest parametru determină tipul mecanismului de citire a fișierului cache. Mecanisme disponibile: verificare ciclică a redundanței, hash MD5 sau verificare simplă a lungimii. Vă rugăm să rețineți că acest mecanism nu este destinat să protejeze fișierele cache împotriva accesului direct de către utilizatori neautorizați. Aceasta este doar o modalitate de a determina dacă un fișier este corupt sau nu;
- pearErrorMode - activează metoda PEAR de returnare a erorilor;
- memoryCaching - de fiecare dată când apelați memoria cache pentru a scrie într-un fișier, acesta este scris în matricea Cache_Lite. saveMemoryCachingState și
getMemoryCachingState sunt folosite pentru a accesa memoria cache stocată în memorie între cereri. Avantajul acestei metode este că conținutul cache-ului poate fi stocat într-un singur fișier, ceea ce reduce numărul de cicluri de citire/scriere pe disc. Cache-ul este restaurat direct într-o matrice la care are acces scriptul;
memoryCachingLimit - parametrul specifică limita numărului de fișiere cache care pot fi stocate într-o matrice în memorie.

goliți memoria cache

Cahce_Lite conține un mecanism de succes pentru determinarea duratei de viață a fișierelor cache, care creează o bază bună pentru siguranța fișierelor dvs. și pentru actualizarea lor în timp util. Cu toate acestea, există momente când trebuie să actualizați imediat fișierul cache. Pentru astfel de cazuri, există metode remove() și clean(). Metoda remove() este concepută pentru a elimina un anumit fișier cache. necesită ID-ul cache-ului și numele grupului căruia îi aparține fișierul. Următorul exemplu va șterge fișierul cache al corpului din exemplul anterior:

$cache->remove("corp", "Dinamic");

Metoda clean() ne permite să ștergem toate fișierele din directorul nostru dacă o numim fără parametri. Dacă treceți numele grupului ca parametru, toate fișierele incluse în acest grup vor fi șterse. Dacă dorim să eliminăm antetul și subsolul, ar trebui să lansăm comenzi similare cu aceasta:

$cache->clean("Static");

Metodele remove() și clean() trebuie în mod evident apelate ca răspuns la evenimentele din cadrul aplicației. De exemplu, dacă aveți un forum, probabil că ar trebui să ștergeți fișierul cache dacă vreun utilizator postează un mesaj nou. Deși această soluție arată bine, poate implica unele modificări de cod. Dacă aveți un script principal care se conectează la fiecare pagină a aplicației pe care o poate vizualiza un vizitator, puteți pur și simplu urmăriți evenimentele care apar, cum ar fi variabila $_GET["newPost"], eliminând fișierele cache necesare. Acest lucru vă va permite să creați un mecanism centralizat de gestionare a memoriei cache. Puteți chiar include acest cod în php.ini.

memorarea în cache a apelurilor la funcții

Deoarece serviciile web sunt expuse în rețea, este adesea o idee bună să memorați rezultatul în cache, astfel încât să poată fi executat local, în loc să rulați aceeași interogare lentă de mai multe ori. În cel mai simplu caz am putea folosi sesiuni PHP, dar deoarece această soluție se bazează pe frecvența vizitatorilor, deschiderea unei cereri pentru fiecare vizitator va fi totuși lentă. În astfel de cazuri, Cache_Lite poate fi foarte util.

Programul de instalare PEAR Web folosește Cache_Lite pentru a stoca în cache cererile XML-RPC trimise către serverul Web PEAR.
Iată codul care primește date de la serverul de la distanță:

$țări = $stationInfo->listCountries();

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

În ambele cazuri, aceste apeluri corespund unei solicitări de date prin rețea. Folosind Cache_Lite, am putea stoca în cache datele returnate de serviciu și le putem reutiliza. Acest lucru ar evita conexiunile suplimentare inutile la rețea și ar crește semnificativ viteza de execuție. Vă rugăm să rețineți că aici ne uităm doar la codul relevant pentru subiectul nostru. Mai întâi activăm Cache_Lite_Function:

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

// Setați parametrii pentru Cache_Lite_Function
// AVERTISMENT: fileNameProtection = TRUE!
$options = array(
"cacheDir" =>"./cache/",
„fileNameProtection” => ADEVĂRAT,
„writeControl” => ADEVĂRAT,
"readControl" => ADEVĂRAT,
"readControlType" => "strlen",
"defaultGroup" =>"SOAP"
);
// Creați un obiect din clasa Cache_Lite_Function
$cache = new Cache_Lite_Function($opțiuni);

Este important ca parametrul fileNameProtection să fie setat la TRUE. Această valoare este implicită, dar am setat-o ​​manual în mod special pentru a-i sublinia semnificația. Setarea acestei opțiuni la FALSE va avea ca rezultat un nume de fișier nevalid, astfel încât stocarea în cache nu va avea loc.
În continuare, facem o solicitare către clientul nostru SOAP:

$țări = $cache->call("stationInfo->listCountries");
$țara = $cache->call("stationInfo->searchByCountry",
$_GET[„țara”]);

Dacă o solicitare este făcută pentru prima dată, Cache_Lite_Function stochează rezultatele ca o matrice serializată într-un fișier cache (nu trebuie să vă faceți griji pentru asta) și acest fișier va fi folosit pentru cererile viitoare până la expirarea duratei sale de viață. setLifeTime poate fi folosit pentru a determina cât timp va dura un fișier cache înainte de a-și actualiza informațiile. Valoarea implicită este 1 oră (3600 secunde).

PEAR::Cache

În general, Cach_Lite oferă un sistem unic, ușor de utilizat pentru a rezolva orice probleme legate de stocarea în cache. Deoarece următorul nivel sunt site-urile cu trafic deosebit de mare, ar trebui să înțelegeți PEAR::Cache - „fratele mai mare” al lui Cache_Lite. De asemenea, oferă capabilități îmbunătățite de stocare în cache, cum ar fi stocarea în memoria cache partajată ca alternativă la stocarea în cache a fișierelor, sau extensia PHP Msession ajută prin stocarea datelor într-o sesiune echilibrată, ceea ce este util în special în serverele web echilibrate. Cache_Lite, însă, oferă mai mult decât suficiente funcții și răspunde nevoilor majorității site-urilor.

cum se gestionează stocarea în cache pe partea client folosind PHP?

Acum că ne-am uitat la opțiunile de suprascrie a memoriei cache pe partea clientului, este timpul să ne uităm la un mecanism care ne va permite să controlăm memoria cache pe partea clientului folosind PHP. Această abordare va funcționa numai dacă utilizați PHP cu un server Apache, deoarece vom folosi funcția getallheaders pentru a obține anteturile trimise de browser. Această funcție funcționează numai în Apache. Dacă utilizați PHP 4.3.0 cu Apache, este posibil să lucrați cu anteturi HTTP folosind funcțiile apache_request_headers și apache_response_headers. Funcția getallheaders a devenit un alias pentru noua funcție apache_request_headers.

Mecanismul de lucru cu memoria cache a browserului web este din nou HTTP. Mai multe antete sunt implicate în instruirea browserelor web și serverelor proxy să memoreze în cache o pagină în mod independent. Situația este complicată de faptul că unele dintre ele sunt disponibile doar cu HTTP 1.1.

verificarea antetelor HTTP în browser

Un instrument simplu, dar foarte convenabil pentru verificarea antetelor cererilor și răspunsurilor este LiveHttpHeaders, un add-on pentru browserul Mozilla. Este important să știți exact ce anteturi trimite scriptul dvs., mai ales când aveți de-a face cu anteturi de cache HTTP.
Pentru simplitate, vom lua în considerare doar anteturile de cache HTTP 1.0, și anume Expires, Last-Modified și If-Modified-Since, precum și codul de stare HTTP 304 (Nemodificat).

Alte anteturi disponibile cu HTTP 1.1, cum ar fi Cache-Control și ETag, sunt menite să ofere un mecanism extins care poate fi utilizat împreună cu starea sesiunii web, cu alte cuvinte, versiunea aceleiași pagini destinată unui vizitator neautorizat poate diferi semnificativ de la afișat pentru utilizatorul autorizat. Antetele HTTP 1.1 au fost adăugate inițial pentru a permite ca astfel de pagini să fie stocate în cache.

expirarea duratei de viață a paginii

Cel mai ușor antet de utilizat este antetul Expire, care stabilește data la care pagina va expira. Până în acest moment, browserului web îi este permis să utilizeze o versiune stocată în cache a paginii.
Exemplu:


function setExpires($expires)(
header("Expiră: " . gmdate("D, d M Y H:i:s", time() + $expires) . "GMT");
}
echo „Această pagină se va autodistruge în 10 secunde
";
ecou "Acum". gmdate("H:i:s") . " GMT
";
ecou"
";
?>

Exemplul de mai sus arată ora actuală GMT și afișează un link care vă permite să reveniți la pagină. Folosind butonul Reîmprospătare al browserului, îi puteți spune browserului că doriți să-și reîmprospăteze memoria cache.

date și ore în HTTP

Datele în HTTP sunt întotdeauna calculate în raport cu Greenwich Mean Time (GMT). Funcția PHP gmdate este exact aceeași funcție cu data, cu excepția faptului că compensează automat GMT în funcție de ceasul sistemului și de setările de regiune ale serverului dvs. Când browserul întâlnește antetul Expires, acesta memorează pagina în cache. Toate solicitările ulterioare pentru pagină făcute înainte de ora TTL specificată utilizează versiunea stocată în cache a paginii, fără a face nicio solicitare către serverul web.
Antetul Expires este simplu de implementat în principiu, dar în majoritatea cazurilor, cu excepția cazului în care sunteți o persoană foarte organizată, nu puteți ști exact când va fi actualizată o anumită pagină de pe site-ul dvs. Deoarece browserul va contacta serverul numai după ce pagina a devenit învechită, nu există nicio modalitate de a-i spune browserului că o pagină din memoria cache a acesteia este învechită.

ora de schimbare a paginii

Este mai practic să folosiți anteturile Last-Modified și If-Modified-Since disponibile în HTTP 1.0. Când utilizați această metodă, trebuie să trimiteți un antet Last-Modified ca răspuns la fiecare solicitare către scriptul dvs. PHP. Data viitoare când browserul solicită pagina, va trimite un antet If-Modified-Since care conține timpul pe care scriptul dumneavoastră îl poate folosi pentru a determina dacă pagina a fost actualizată de la ultima solicitare. Dacă nu este cazul, scriptul dvs. trimite un cod de stare HTTP 304 pentru a indica faptul că pagina nu s-a schimbat, fără a imprima conținutul paginii. Dacă combinați ultima abordare a timpului modificat cu o valoare a timpului care este deja disponibilă în aplicația dvs. (de exemplu, ora celui mai recent articol de știri), puteți profita de memoria cache a browserului web și puteți descărca linkul de date, salvând informații. trafic de pe site-ul dvs., acolo unde este posibil, îmbunătățirea performanței acestuia.

Fiți atenți când testați orice stocare în cache făcută în acest stil: dacă o faceți incorect, puteți determina vizitatorii dvs. să aibă întotdeauna copii învechite ale site-ului dvs.

Harry Fuecks, traducere de Sergey Mullin (SiMM) și Kuzma Feskov.

Nu este un secret că, cu cât un site se încarcă mai repede, cu atât va fi mai convenabil pentru utilizatori. Dacă paginile se încarcă rapid, utilizatorii nu vor părăsi site-ul dvs., iar motoarele de căutare vă vor trata mai bine site-ul. Pentru multe site-uri web moderne, motorul de execuție a scripturilor dinamice PHP devine un blocaj.

Serverul web Nginx, atunci când este configurat corect, poate servi instantaneu un număr mare de pagini, ceea ce nu se poate spune despre generarea paginii poate dura până la câteva secunde; Dar PHP poate fi accelerat și folosind memorarea în cache. În acest articol ne vom uita la modul în care este configurată memorarea în cache PHP, cum este și de ce este necesară. De exemplu, vom folosi o combinație de php-fpm și Nginx, dar informațiile din articol sunt potrivite și pentru alte opțiuni de instalare.

Particularitatea limbajelor interpretate este că de fiecare dată când se lansează un script, interpretul trebuie să compileze programul și să îl verifice pentru erori. Dar ne putem deplasa. Există două tipuri principale de stocare în cache:

  • Memorarea în cache a paginilor gata- pagina este generată de PHP, iar apoi pagina finalizată este dată utilizatorului fără a accesa PHP. Vă voi spune cum să faceți acest lucru folosind fastcgi, dar nu vă recomand să folosiți această metodă pentru Wordpress sau alte motoare, este mai bine să le puneți în cache folosind plugin-uri speciale;
  • Memorarea în cache a codului de octeți și a instrucțiunilor- și acest lucru este deja interesant, nu întreaga pagină este stocată în cache, ci doar câteva instrucțiuni și bucăți de cod octet care nu se schimbă la apelarea scriptului. Înainte de a executa un script, interpretul trebuie să-l convertească într-un format pe care să-l înțeleagă la memorarea în cache, o astfel de conversie se efectuează doar la prima rulare, iar apoi este preluată versiunea din cache;
  • Memorarea în cache a sesiunii- implicit, php salvează sesiunile utilizatorilor în fișiere și îi putem accelera puțin lucrul dacă salvăm sesiunile în RAM.

Memorarea în cache bytecode în PHP

Începând cu PHP 5.5, la interpretul de limbă a fost adăugat suport pentru stocarea în cache a bytecode din ZendFramework. În versiunile noi, acest cache vă permite să creșteți foarte mult performanța resursei dvs., de exemplu, există informații că Wordpres și alte motoare rulează aproape de două ori mai repede pe PHP 7; Înainte de a configura opcode php caching-ul, trebuie să instalați pachetul acestuia:

sudo apt install php-opcache

Sau pentru distribuțiile Red Hat:

sudo yum instalează php-opcache

Apoi, pentru a activa stocarea în cache, trebuie să adăugați câteva linii la php.ini, puteți crea și un fișier separat în /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;

Să ne uităm la ce înseamnă aceste linii pentru a ști ce valori să setați. Prima linie încarcă extensia, nu trebuie schimbat nimic aici.

  • opcache.error_log- specifică fișierul pentru înregistrarea jurnalului de erori, care va fi util pentru depanare;
  • opcache.log_verbosity_level- indică cât de detaliat ar trebui să fie fișierul jurnal, valoare de la 1 la 4;
  • opcache.enable- permite stocarea în cache;
  • opcache.enable_cli- permite stocarea în cache a paginilor php pentru versiunea de consolă;
  • opcache.consum_memorie- cantitatea de memorie RAM pentru stocarea în cache;
  • opcache.max_accelerated_files- numărul de scripturi/fișiere care trebuie să fie stocate în cache;
  • opcache.validate_timestamps- verifica ora schimbarii datelor in fisierul script;
  • opcache.revalidate_freq- frecvența verificării parametrului anterior;
  • opcache.revalidate_path- setați la 0 pentru a verifica include doar prima dată;
  • opcache.enable_file_override- memorează în cache cererile pentru atributele fișierului, de exemplu, existența etc.;
  • opcache.blacklist_filename- o listă de fișiere care nu trebuie să fie stocate în cache;
  • opcache.max_file_size- dimensiunea maximă a fișierului script pentru stocarea în cache, 0 - nelimitat;
  • opcache.interned_strings_buffer- numărul permis de linii în buffer;
  • opcache.fast_shutdown- utilizați o modalitate rapidă de a elibera memorie.

După ce ați salvat toate setările, tot ce trebuie să faceți este să reporniți php sau serverul dvs. web:

systemctl reporniți php-fpm

Pentru a vă asigura că totul funcționează, poate doriți să vedeți ce scripturi sunt deja stocate în cache. Puteți utiliza scriptul opcache-status pentru aceasta. Doar salvați scriptul în directorul serverului dvs. web și apoi acordați-i permisiuni:

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

http://localhost/opcache.php

Aici puteți vedea statistici detaliate despre stocarea în cache, setări și cantitatea de memorie ocupată.

Stocarea sesiunilor în memcached

Implicit, php stochează sesiuni în sistemul de fișiere, în unele cazuri, puteți accelera semnificativ php dacă transferați stocarea sesiunilor din fișiere în RAM, de exemplu, memcached. Mai întâi trebuie să instalați memcached și biblioteca php pentru a lucra cu el:

sudo apt install memcached php-memcached

Sau pentru sisteme bazate pe Red Hat:

sudo yum install memcached php-memcached

Mai întâi trebuie să configuram memcached, să deschidem fișierul /etc/sysconfig/memcached și să găsim linia CACHESIZE, aici trebuie să specificați cantitatea de RAM care este alocată pentru cache:

vi /etc/sysconfig/memcached

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

Tot ce rămâne este să reporniți interpretul php:

systemctl reporniți php-fpm

Dacă doriți să verificați dacă totul este în cache corect și dacă există ceva în cache, puteți utiliza phpmemcacheadmin .

Memorarea în cache a paginilor fastcgi

Nu recomand să folosiți fastgci caching pentru site-urile WordPress deoarece există plugin-uri speciale care pot controla cu precizie memoria cache, o pot șterge atunci când este necesar și o pot actualiza la timp. Dar în toate celelalte cazuri, memoria cache fastcgi poate accelera foarte mult site-ul. Este configurat în configurația în care activați fastgci, de exemplu, în configurația serverului web Nginx. Modul minim de a configura memoria cache fastgci este să adăugați următoarele linii la blocul serverului:

vi /etc/nginx/vhosts/site.conf

fastcgi_cache_path /var/nginx/cache levels=1:2 keys_zone=MYAPP:100m inactiv=60m;
fastcgi_cache_key „$scheme$request_method$gazdă$request_uri”;

Prima linie configurează mai mulți parametri simultan, în primul rând, adaugă calea în cache, puteți folosi oricare, atâta timp cât folderul există și serverul web are drepturi de a scrie în el. Directiva levels specifică câte subdosare vor exista. Următoarea linie specifică ce va fi folosită ca cheie pentru cache. Cheia va fi hashing în md5.

Acum trebuie să configurați blocul de procesare php:

locație ~ \.php$ (
fastcgi_pass unix:/var/run/php7-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_cache MYAPP;
fastcgi_cache_valid 200 60m;
}

Aici accesăm zona de memorie MYAPP deja configurată și, de asemenea, specificăm o durată de viață a cache-ului de o oră. Pentru a verifica stocarea în cache, puteți vizualiza conținutul folderului:

ls -lR /var/nginx/cache/

Cu aceste metode, paginile dvs. se vor încărca mult mai repede. Dacă trebuie să dezactivați memorarea în cache php pentru pagini individuale, atunci creați mai întâi variabila no_cache cu valoarea 0:

setează $no_cache 0;

Apoi verificăm parametrii necesari, iar dacă se potrivesc, setăm valoarea la 1:

dacă ($request_method = POST)
{
setați $no_cache 1;
}

Și pentru a termina, trecem valoarea acestei variabile la următoarele directive, aceasta va dezactiva stocarea în cache atunci când nu este nevoie:

fastcgi_cache_bypass $no_cache;
fastcgi_no_cache $no_cache;

Pentru a optimiza lucrul cu rețeaua, se folosește un mecanism de salvare a documentelor odată primite prin HTTP într-un cache cu scopul de a le reutiliza fără a contacta serverul sursă. Un document salvat în cache va fi disponibil la următoarea accesare, fără descărcare de pe serverul sursă, ceea ce are scopul de a crește viteza de acces a clientului la acesta și de a reduce consumul de trafic de rețea.

Cache-urile în sine sunt de două tipuri: locale și partajate. Local este un cache stocat direct pe discul clientului, creat și gestionat de browserul acestuia. General este memoria cache proxy a unei organizații sau a furnizorului și poate consta din unul sau mai multe servere proxy. Un cache local este prezent, probabil în fiecare browser o parte semnificativă a persoanelor care folosesc Internetul le folosesc pe cele comune. Și dacă o mică parte din site-uri sunt acum evaluate în funcție de consumul de trafic, atunci viteza de încărcare este un criteriu important care trebuie luat în considerare atunci când vă dezvoltați proiectul web.
Pentru paginile dinamice create ca urmare a unui program PHP, memorarea în cache ar părea dăunătoare. Conținutul paginii este format la cererea utilizatorului pe baza oricărei surse de date. Cu toate acestea, memorarea în cache poate fi utilă. Prin gestionarea acestuia, puteți face lucrul cu serverul dvs. mai confortabil pentru utilizator, permițând încărcarea anumitor pagini din cache, împiedicând astfel reîncărcarea lor de pe serverul dvs. și economisind timp și trafic utilizatorului.

Pentru cache sau nu?

Capacitatea de a salva o pagină în cache este determinată de dinamica informațiilor din sursa de date. Astfel, necesitatea folosirii unui cache este determinată de dvs. în funcție de durata de viață planificată a paginii.

Dacă vorbim despre formarea unui eșantion din baza de date (de exemplu, căutarea unui cuvânt introdus de utilizator), atunci o astfel de pagină trebuie solicitată de la server la fiecare apel fără a utiliza un cache, deoarece numărul de variante ale cuvintele solicitate sunt uriașe și, dacă avem de-a face și cu schimbarea matricei de date, atunci stocarea în cache este inutilă. Sau vorbim despre formarea, să zicem, a unui program de vizitatori care sosesc (care se schimbă cu fiecare vizită, adică cu aproape fiecare apel), atunci memorarea în cache este pur și simplu dăunătoare.

Totuși, dacă vorbim despre același grafic, dar pentru ziua de ieri, atunci se recomandă memorarea în cache, deoarece datele nu se vor mai modifica și putem economisi noi și utilizatorii resurse și timp pentru încărcarea unor astfel de pagini, plasându-le într-un cache local sau partajat. . Ca o continuare a acestei situatii, formarea unui program nu se face in timp real, ci orar. Aici puteți prezice în avans data de expirare a datelor generate.

Principii generale pentru stocarea paginilor în cache

Un program PHP poate controla stocarea în cache a rezultatelor muncii sale prin formarea de câmpuri suplimentare în antetul răspunsului HTTP apelând funcția Header().
Câteva afirmații generale tipice nu numai pentru programele PHP:

  • Paginile trimise prin POST nu sunt niciodată memorate în cache.
  • Paginile solicitate prin GET și care conțin parametri (URL-ul conține „?”) nu sunt stocate în cache decât dacă se specifică altfel.

Astfel, în majoritatea situațiilor nu este nevoie să adăugați instrucțiuni suplimentare la program. Principalele puncte la care trebuie să acordați atenție pot fi reduse la două:

  • dezactivați memorarea în cache a documentelor memorate în cache în mod implicit
  • Memorarea în cache a documentelor care nu sunt memorate în cache în mod implicit.

Preveniți stocarea în cache a documentelor care sunt memorate în cache în mod implicit

Această problemă apare pentru scripturile PHP care sunt apelate fără parametri sau sunt indexuri ale directoarelor, dar generează date personal pentru utilizator (de exemplu, pe baza cookie-urilor sau user agent) sau funcționează pe baza unor date care se schimbă rapid. Conform specificației HTTP/1.1, putem gestiona următoarele câmpuri:

Expiră
Specifică data de expirare a documentului. Setarea acestuia în trecut determină că memoria cache este dezactivată pentru această pagină.

Cache-control: fără cache
Gestionarea cache-ului. Valoarea fără cache determină dacă memoria cache a acestei pagini este dezactivată. Pentru versiunea de protocol HTTP/1.0, se aplică „Pragma: no-cache”.

Modificat ultima dată
Data la care conținutul a fost modificat ultima dată. Câmpul este relevant doar pentru paginile statice. Apache înlocuiește acest câmp cu valoarea câmpului Data pentru paginile generate dinamic, inclusiv paginile care conțin SSI.

Site-ul web www.php.net oferă următorul cod pentru a dezactiva stocarea în cache.

header(„Expiră: Luni, 26 iulie 1997 05:00:00 GMT”); // Data în trecut
header("Ultima modificare: " . gmdate ("D, d M Y H:i:s") . " GMT"); // mereu modificat
header("Control-cache: fără cache, trebuie revalidat"); // HTTP/1.1
header("Pragma: fără cache"); // HTTP/1.0

Cu toate acestea, acest antet este redundant. În majoritatea cazurilor este suficient:

Pentru a marca un document ca „învechit”, ar trebui să setați Expires egal cu câmpul Data.
header("Expiră: " . gmdate ("D, d M Y H:i:s") . " GMT");

Ei bine, nu trebuie să uităm că formularele solicitate prin POST nu sunt, de asemenea, supuse memorării în cache.

Memorarea în cache a documentelor care nu sunt memorate în cache în mod implicit

Problema inversă poate părea absurdă la prima vedere. Cu toate acestea, este nevoie și de acest lucru. Pe lângă reducerea la minimum a traficului, atunci când dezvoltați un program web, ar trebui să țineți cont de confortul utilizatorului cu acesta. De exemplu, unele pagini ale serverului dvs. sunt formate pe baza datelor statice de volum mare. Capacitatea de a le include în cache va îmbunătăți semnificativ viteza serverului pentru utilizator și vă va elibera parțial de numeroasele generații repetate ale unei astfel de pagini. Antet care permite salvarea pe serverele proxy:

Articol înrudit: Promovarea motorului de căutare a unui magazin online în Yandex și Google: listă de verificare pentru auditarea factorilor de clasare


Dacă o pagină ia în considerare informațiile stocate în browserul utilizatorului (tipul și versiunea browserului, chei, autorizare etc.), o astfel de pagină nu poate fi salvată în proxy, dar poate fi salvată în memoria cache a browserului local:

header("Controlul cache: privat");

Memorarea în cache până la expirarea valabilității

Soluțiile descrise mai sus sunt destul de simple, deși potrivite pentru majoritatea problemelor. Dar protocolul HTTP/1.1 are instrumente pentru o gestionare mai precisă a memoriei cache a paginilor și există sarcini care necesită utilizarea acestor mecanisme. De exemplu, aplicațiile web care funcționează cu date de volum mare și dinamică previzibilă. Corectitudinea datelor poate fi determinată atât de data actualizării prezise, ​​cât și de modificările de conținut. Pentru aceste cazuri sunt utilizate diferite antete de control al memoriei cache.

Memoria cache de reîmprospătare predictivă

Să luăm în considerare un exemplu - o listă de prețuri actualizată luni. Știți dinainte că conținutul paginii poate fi stocat în cache până la începerea noii săptămâni, ceea ce ar trebui să fie indicat în antetul de răspuns pentru a asigura comportamentul dorit al paginii în cache.
Sarcina principală este să obțineți data de luni viitoare în format RFC-1123

$dt_tmp=getdate(data("U"));
antet("Expiră: " . gmdate("D, d M Y H:i:s", data("U")-(86400*($dt_tmp["wday"]-8))) . " GMT");
header("Controlul cache: public");

Această metodă poate controla eficient comportamentul unei pagini din cache și este aplicabilă pentru un număr mare de pagini - într-un fel sau altul, este posibil să se selecteze intervale de timp în care conținutul paginii rămâne constant. Realitatea este că paginile celor mai multe site-uri dinamice au o anumită durată de viață pe baza căreia dezvoltatorul poate crea o experiență mai plăcută pentru utilizator.

O altă abordare, folosită atunci când informațiile sunt actualizate mai rapid și în același timp trafic mare către server (altfel stocarea în cache nu va fi eficientă) este utilizarea antetului Cache-control: max-age=seconds, care determină timpul după care documentul este considerat învechit și are o prioritate mai mare la calcularea „prospețimii” documentului.

Cache este un buffer intermediar special cu acces foarte rapid, care conține date care sunt cel mai probabil să fie solicitate.

Ce este memorarea în cache?

Pentru a optimiza lucrul cu rețeaua, se folosește un mecanism de salvare a documentelor primite o dată prin HTTP într-un cache pentru reutilizarea lor, fără a contacta serverul sursă. Documentul care este salvat în cache va fi disponibil data viitoare când îl accesați, fără a-l descărca de pe serverul sursă. Acesta este conceput pentru a crește viteza de acces a clientului la acesta, precum și pentru a reduce consumul de trafic de rețea.

Astăzi, există două tipuri de cache - locale și partajate.

  • Local - un cache stocat pe discul clientului, creat și gestionat de browserul său de internet.
  • General este memoria cache a serverului proxy al furnizorului, poate consta dintr-unul sau mai multe servere proxy.

Există un cache local, probabil în fiecare browser de Internet, cele comune sunt folosite de majoritatea oamenilor care folosesc Internetul. Iar dacă o mică parte din site-urile de astăzi sunt evaluate în funcție de consumul de trafic, atunci viteza de încărcare este un criteriu foarte important de care trebuie luat în considerare atunci când dezvoltați proiectul dvs. web.

Pentru paginile dinamice care sunt create ca urmare a unei aplicații PHP, memorarea în cache ar părea a fi foarte dăunătoare. Conținutul paginii este format la cererea utilizatorului pe baza unei anumite surse de informații. Cu toate acestea, memorarea în cache poate fi utilă. Gestionând-o, puteți face lucrul cu serverul dvs. mult mai convenabil pentru utilizator, permițând încărcarea anumitor pagini din cache, prevenind astfel reîncărcarea lor de pe server și economisind traficul și timpul utilizatorului.

Principii cheie pentru stocarea paginilor în cache

O aplicație PHP poate controla stocarea în cache a rezultatelor muncii sale prin formarea de câmpuri suplimentare în antetul răspunsului HTTP apelând funcția specială Header().

Câteva afirmații generale care nu se limitează la aplicațiile PHP:

  • Paginile transmise prin POST nu sunt niciodată salvate în cache.
  • Paginile care sunt solicitate prin GET și care conțin parametri (URL-ul conține „?”) nu sunt salvate în cache dacă nu se specifică altfel.

În majoritatea situațiilor, nu este nevoie să adăugați instrucțiuni suplimentare la aplicație. Puncte cheie la care trebuie să acordați atenție:

  • interzicerea stocării în cache a documentelor care sunt memorate implicit în cache;
  • memorarea în cache a documentelor care nu sunt memorate în cache în mod implicit.

Interzicerea stocării în cache a documentelor (care sunt memorate în cache în mod implicit)

Această problemă apare pentru scripturile PHP care sunt apelate fără parametri sau sunt indexuri de directoare, dar generează informații personal pentru utilizator (de exemplu, pe baza agentului utilizator sau cookie-uri) sau funcționează pe baza informațiilor care se schimbă rapid. Conform specificației HTTP/1.1, putem gestiona următoarele câmpuri:

  1. Expiră - specifică data de expirare a unui anumit document. Setarea acestuia în trecut determină că memoria cache este dezactivată pentru această pagină.
  2. Cache-control: no-cache - control cache. Valoarea fără cache determină dacă memoria cache a acestei pagini este dezactivată. Pentru versiunea de protocol HTTP/1.0, aici se aplică „Pragma: no-cache”.
  3. Ultima modificare este data la care conținutul specific a fost modificat ultima dată. Câmpul este folosit exclusiv pentru pagini statice. Apache înlocuiește acest câmp cu valoarea câmpului Date pentru paginile generate dinamic, în special pentru paginile care conțin SSI.

Pentru a dezactiva stocarea în cache, scrieți:

Pentru a marca un document ca „învechit”, trebuie să setați Expires egal cu câmpul Data.

Antet ("Expiră: " . gmdate ("D, d M Y H:i:s") . " GMT");

De asemenea, nu trebuie să uităm că formularele care sunt solicitate prin POST nu pot fi stocate în cache.

Memoria cache de reîmprospătare predictivă

Să luăm în considerare un exemplu - o listă de prețuri actualizată luni. Știți dinainte că conținutul paginii poate fi stocat în cache până în săptămâna viitoare, ceea ce ar trebui să fie indicat în antetul răspunsului, asigurând comportamentul necesar al paginii în cache.

Sarcina principală aici este să obțineți data de luni viitoare sub forma RFC-1123.

$dt_tmp=getdate(data("U")); antet("Expiră: " . gmdate("D, d M Y H:i:s", data("U")-(86400*($dt_tmp["wday"]-8))) . " GMT"); header("Controlul cache: public");

Această metodă poate controla foarte eficient comportamentul unei pagini din cache. Puteți selecta intervale speciale de timp în care conținutul unei anumite pagini rămâne constant.

O altă abordare, care este utilizată atunci când se actualizează datele mai rapid și în același timp trafic mare către server (altfel stocarea în cache nu va fi eficientă) este utilizarea unui antet special Cache-control: max-age=seconds, care determină timpul după care documentul este considerat depășit și având o prioritate mult mai mare la calcularea prospețimii unui anumit document.

Dacă publicați știri la intervale de 60 de minute:

Antet ("Cache-control: public"); header("Controlul cache: vârsta maximă=3600");

Implementarea memoriei cache în PHP

Trebuie să creați două fișiere speciale. Primul va face ieșire cache, iar al doilea va crea cache.

Să începem cu primul fișier, pe care îl vom numi read_cache.php.

În acest script, obținem numele fișierului, apoi verificăm dacă există un astfel de cache, apoi îl scoatem și terminăm lucrarea sau deschidem un buffer în care vom plasa toată ieșirea scriptului.

Acum să creăm un fișier special scrie_cache.php. Va scrie într-un fișier ceea ce s-a acumulat în buffer.

Acum, în orice fișier PHP care este responsabil pentru ieșire, puteți activa stocarea în cache:

Acum puteți începe să memorați în cache toate paginile problematice. Cu toate acestea, rețineți că atâta timp cât memoria cache este în viață, utilizatorul nu va vedea nicio actualizare. În acest sens, faceți cache în PHP doar pentru acele pagini care sunt actualizate foarte rar.

Pe vremuri bune, când crearea de site-uri web era la fel de simplă ca și tastarea câtorva pagini HTML, trimiterea paginilor web către browser era o chestiune simplă de trimitere de fișiere de către serverul web. Vizitatorii site-ului puteau vedea aceste pagini mici, doar text, aproape instantaneu (cu excepția utilizatorilor modemurilor lente). Odată ce pagina a fost încărcată, browserul o memorează în cache undeva pe computerul local, astfel încât, dacă pagina este solicitată din nou, să poată prelua versiunea locală din cache, trimițând doar o scurtă solicitare pentru a se asigura că pagina de pe server nu are fost modificată. Solicitările au fost procesate rapid și cât mai eficient posibil, iar toată lumea a fost mulțumită (cu excepția celor care foloseau modemuri de 9600 baud).

Apariția paginilor web dinamice a schimbat lucrurile în rău, rupând efectiv acest model de servire a paginilor web din cauza a două probleme:

Când serverul primește o solicitare pentru o pagină web dinamică, se efectuează unele procesări intermediare, cum ar fi analizarea scriptului de către motorul PHP, care trebuie finalizată. Datorită acestui fapt, avem o întârziere înainte ca serverul web să înceapă să trimită rezultate către browser. Pentru un script PHP simplu, acest lucru nu este semnificativ, dar pentru o aplicație mai complexă, motorul PHP poate efectua multe acțiuni înainte ca pagina să fie gata pentru a fi trimisă. Acești pași suplimentari au ca rezultat o întârziere vizibilă între solicitările utilizatorilor și paginile care sunt afișate efectiv în browserele lor.

Un server web obișnuit, cum ar fi Apache, folosește timpul de modificare a fișierelor pentru a spune corect browserului web starea cache a paginii solicitate. Pentru paginile web dinamice, script-ul PHP real se poate schimba doar ocazional, în timp ce conținutul pe care îl afișează, eventual rezident într-o bază de date, se modifică frecvent. Serverul Web nu are de unde să știe că au existat modificări în baza de date, dar nu trimite data ultimei modificări. În cazul în care clientul (browserul) nu primește nicio indicație despre cât timp datele sunt corecte, presupune că va trebui să solicite o nouă pagină data viitoare. Serverul web va răspunde întotdeauna cu o versiune actualizată a paginii, indiferent dacă datele s-au modificat. Pentru a evita acest neajuns, majoritatea dezvoltatorilor web folosesc metaetichete sau anteturi HTTP pentru a spune browserului să nu folosească niciodată versiunea stocată în cache a paginii. Cu toate acestea, acest lucru anulează capacitatea naturală a browserului web de a stoca în cache paginile web și are unele dezavantaje semnificative. De exemplu, conținutul unei pagini dinamice se poate schimba o dată pe zi, astfel că beneficiul obținut de a avea browserul în cachea paginii chiar și pentru 24 de ore este evident.

De obicei, pentru aplicațiile PHP mici este destul de posibil să ignorați existența acestor probleme, totuși, pe măsură ce complexitatea și traficul site-ului dvs. cresc, puteți întâmpina probleme. Cu toate acestea, ambele probleme pot fi rezolvate, prima prin memorarea în cache pe partea de server, a doua prin gestionarea stocării în cache pe partea clientului din cadrul aplicației dumneavoastră. Abordarea pe care o luați pentru a rezolva problemele va depinde de aplicația dvs., dar în acest capitol vom vedea cum puteți rezolva ambele probleme folosind PHP și unele clase de bibliotecă PEAR.

Vă rugăm să rețineți că capitolul Caching discută doar soluțiile implementate folosind PHP. Ele nu trebuie confundate cu soluțiile de stocare în cache a scripturilor, care funcționează prin optimizarea și stocarea în cache a scripturilor PHP compilate. Acest grup poate include Zend Accelerator, ionCube PHP Accelerator, Turck MMCache/eaccelerator, APC.

Cum împiedic browserele să memoreze o pagină în cache?

Înainte de a ne uita la tehnicile de stocare în cache pentru client și server, trebuie mai întâi să înțelegem cum să împiedicăm browserele web (și serverele proxy) să memoreze paginile în cache. Principala modalitate de a realiza acest lucru este utilizarea metaetichetelor HTML:

„Luni, 26 iulie 1997 05:00:00 GMT” />

Prin inserarea unei date trecute în metaeticheta Expires, îi spuneți browserului că copia stocată în cache a paginii este întotdeauna învechită. Aceasta înseamnă că browserul nu ar trebui să memoreze pagina în cache. Meta tag Pragma: no-cache este o convenție destul de bine acceptată pe care o urmează majoritatea browserelor web. Odată ce detectează această etichetă, de obicei nu pun în cache pagina (deși nu există nicio garanție, aceasta este doar o convenție).

Sună bine, dar există două probleme cu utilizarea metaetichetelor:

Dacă eticheta nu exista atunci când pagina a fost solicitată prima dată de browser, dar apare mai târziu (de exemplu, ați modificat fișierul de includere pageheader.php care este antetul fiecărei pagini web), browserul va rămâne fără cunoștință și va folosi copie stocată în cache a originalului.

Serverele proxy care memorează în cache pagini web, cum ar fi un ISP partajat, nu vor examina deloc direct conținutul documentului HTML. În schimb, se bazează doar pe serverul web de la care provin documentele și pe protocolul HTTP. Cu alte cuvinte, browserul web poate crede că nu ar trebui să memoreze pagina în cache, dar serverul proxy dintre browser și serverul dvs. web probabil că nu știe acest lucru - și va continua să trimită aceeași pagină, acum învechită, către client. .

O abordare mai bună este să utilizați protocolul HTTP direct folosind funcția de antet PHP, echivalentă cu cele două metaetichete de mai sus:

antet(); header("Pragma: fără cache");

Putem face un pas mai departe utilizând antetul Cache-Control, care este compatibil cu browserele care acceptă HTTP 1.1:

antet ( „Expiră: Luni, 26 iulie 1997 05:00:00 GMT”); antet ( „Cache-Control: fără stocare, fără cache, revalidare obligatorie”); antet ( „Cache-Control: post-check=0, pre-check=0”, FALS ) ; header("Pragma: fără cache");

Acest lucru asigură că niciun browser web sau server proxy intermediar nu memorează pagina în cache, astfel încât vizitatorii primesc întotdeauna cea mai recentă versiune a conținutului. De fapt, primul antet ar trebui să fie autonom, acesta este cel mai bun mod de a vă asigura că pagina nu este stocată în cache. Titluri Cache-ControlȘi Pragma adăugată în scopul „asigurării”. Deși nu funcționează în toate browserele sau proxy-urile, vor prinde unele cazuri în care Expiră nu funcționează conform așteptărilor (de exemplu, dacă data de pe computerul clientului nu este setată corect).

Desigur, evitarea stocării în cache ne prezintă în totalitate problemele pe care le-am discutat la începutul acestui capitol. Acum ne vom uita la rezolvarea acestor probleme. Internet Explorer și descărcarea fișierelor în cache

Discuția noastră despre PDF din Capitolul 3, Tipuri alternative de conținut, a explicat că pot apărea probleme atunci când aveți de-a face cu stocarea în cache și descărcarea fișierelor. Dacă, la deservirea unui fișier descărcat printr-un script PHP, anteturi precum Conținut-Dispoziție: atașament, filename=myFile.pd pentru Content-Disposition: inline, filename=myFile.pdf, veți avea probleme cu Internet Explorer dacă îi spuneți browserului să nu memoreze pagina în cache.

Internet Explorer gestionează descărcările într-un mod destul de neobișnuit, făcând două solicitări către site. Prima solicitare descarcă fișierul și îl stochează în cache până când se face a doua solicitare (fără a stoca răspunsul). Această solicitare face ca fișierul să fie transferat către utilizatorul final în funcție de tipul de fișier (de exemplu, lansează Acrobat Reader dacă fișierul este un document PDF). Aceasta înseamnă că, dacă trimiteți anteturi care împiedică browserul să memoreze pagina în cache, Internet Explorer va șterge fișierul între prima și a doua solicitare, rezultând nimic pentru utilizatorul final. Dacă fișierul pe care îl serviți cu un script PHP nu se modifică, una dintre cele mai simple soluții este să eliminați anteturile „inhibarea caching-ului” din script.

Dacă fișierul descărcat se modifică în mod regulat (adică doriți ca browserul să descarce cea mai nouă versiune), ar trebui să utilizați antetul Modificat ultima dată, care va fi discutat mai târziu în acest capitol, și să vă asigurați că timpul de modificare dintre două solicitări consecutive nu se modifică. Trebuie să faceți acest lucru într-un mod care să nu afecteze utilizatorii browserelor care gestionează corect descărcările. O soluție în acest caz ar fi să stocați fișierul pe serverul dvs. web și să furnizați un link simplu către acesta, permițând serverului web să vă raporteze anteturile de cache. Desigur, această soluție poate să nu fie acceptabilă dacă se presupune accesul autorizat la fișier, această soluție permite încărcarea directă a fișierului salvat.

Cum pot captura date pe partea serverului pentru stocare în cache?

Este timpul să ne uităm la modul în care putem reduce latența utilizând stocarea în cache a ieșirilor de pe partea serverului. Abordarea generală este să începeți să serviți pagina ca de obicei, să faceți interogări la baza de date și așa mai departe în PHP. Cu toate acestea, înainte de a trimite rezultatul către browser, îl captăm și salvăm pagina finalizată, de exemplu, într-un fișier. La următoarea solicitare, scriptul PHP verifică mai întâi o versiune în cache a paginii. Dacă există, scriptul trimite versiunea în cache la browser, eliminând astfel întârzierea re-creării paginii.

Câteva cuvinte despre stocarea în cache folosind șabloane

Motoarele de șabloane precum Smarty vorbesc adesea despre stocarea în cache a șabloanelor. De obicei, aceste motoare oferă un mecanism încorporat pentru salvarea unei versiuni compilate a șablonului (adică, generarea sursei PHP din șablon), ceea ce ne împiedică să analizăm șablonul de fiecare dată când este solicitată o pagină. Acest lucru nu trebuie confundat cu stocarea în cache a ieșirii, care se referă la stocarea în cache a HTML-ului furnizat (sau a altor rezultate) pe care PHP o trimite către browser. Puteți utiliza cu succes ambele tipuri de stocare în cache simultan pe același site.

Ne vom uita acum la mecanismul de stocare în cache încorporat al PHP care utilizează buffering de ieșire, pe care îl puteți utiliza indiferent de modul în care vă creați conținutul (cu sau fără șabloane). Luați în considerare o situație în care scriptul dvs. afișează rezultatul folosind, de exemplu, ecou sau imprimare pentru a scoate date direct în browser. În acest caz, puteți utiliza funcțiile de control de ieșire ale PHP pentru a stoca date în memoria tampon, asupra căreia scriptul dumneavoastră PHP are atât acces, cât și control.

Iată un exemplu simplu:

Exemplul 5.1. 1.php

Ob_start(); // Afișează un text (care este salvat în buffer); ecou „1. Noi scoatem acest lucru în buffer
"
; // Opriți stocarea tampon și ștergeți tamponul de ieșire ob_end_clean(); // Afișează un text ca de obicei ecou „2. Ieșire normală
"
; // Imprimați conținutul tamponului echo $buffer ;

Buffer-ul în sine stochează ieșirea ca șir. Deci, în scriptul de mai sus, începem să punem în buffer cu ob_start și să folosim echo pentru a scoate ceva. Apoi folosim ob_get_contents pentru a prelua datele stocate în tampon de instrucțiunea echo și pentru a le stoca într-un șir. Funcția ob_end_clean oprește stocarea de ieșire și șterge conținutul acestuia, alternativ, ob_end_flush poate fi folosit pentru a șterge conținutul bufferului.

Scriptul de mai sus va scoate:

2. Ieșire normală 1. Trimiteți acest lucru în buffer

Cu alte cuvinte, am capturat rezultatul primului ecou, ​​apoi l-am trimis în browser după al doilea ecou. După cum puteți vedea din acest exemplu simplu, tamponarea de ieșire este un instrument foarte puternic pentru modelarea site-ului dvs., oferă o soluție de stocare în cache, așa cum vom vedea în curând și este o modalitate excelentă de a ascunde erorile de la vizitatorii site-ului dvs. (vezi capitolul 10, Tratarea erorilor). De asemenea, oferă o opțiune alternativă pentru redirecționarea browserului în situații precum autentificarea utilizatorului.

Antete HTTP și buffering de ieșire

Bufferingul de ieșire poate ajuta la rezolvarea celei mai frecvente probleme cu funcția de antet, ca să nu mai vorbim de session_start și set_cookie. De obicei, dacă apelați oricare dintre aceste funcții după ce pagina a început redarea, veți primi un mesaj de eroare urât. Când tamponarea de ieșire este activată, singurul tip de ieșire care evită stocarea în tampon sunt anteturile HTTP. Folosind ob_start chiar la începutul execuției aplicației, puteți trimite anteturi în orice moment al programului care vă place, fără a întâmpina erorile obișnuite. Apoi, odată ce sunteți sigur că nu mai trebuie să imprimați alte anteturi HTTP, puteți imprima imediat conținutul paginii din buffer. (nota traducătorului: trebuie remarcat faptul că o astfel de utilizare a acestei funcții este extrem de nejustificată. În cele mai multe cazuri, necesitatea de a utiliza buffering de ieșire pentru a scăpa de erori de acest tip pur și simplu nu există și totul poate fi corectat cu ușurință printr-un design adecvat al aplicației )

Utilizarea tamponării de ieșire pentru stocarea în cache pe server

Ați văzut deja un exemplu de bază de buffering de ieșire, acum următorul pas este în cazul în care tamponul este salvat într-un fișier:

Exemplul 5.2. 2.php

// Dacă există o versiune în cache... dacă (fișier_există ("./cache/2.cache" ) ) ( // Citiți și scoateți fișierul readfile ("./cache/2.cache" ); Ieșire(); ) // Porniți ieșirea în buffer ob_start(); // Afișează restul HTML-ului ?> Pagina stocată în cache "http://www.php.net/outcontrol">Funcții de control a ieșirii // Obține conținutul bufferului$buffer = ob_get_contents(); // Opriți stocarea tampon și scoateți bufferul ob_end_flush(); // Salvarea unui fișier cache cu conținut$fp = fopen ("./cache/2.cache" , "w" ); fwrite($fp, $buffer); fclose($fp);

Mai întâi, scriptul de mai sus verifică dacă o versiune a paginii există în cache și, dacă există, scriptul o citește și o afișează. În caz contrar, folosește buffering de ieșire pentru a crea o versiune stocată în cache a paginii. Este salvat ca fișier după folosirea ob_end_flush pentru a afișa pagina utilizatorului.

Fișierul 2.cache conține o copie exactă a codului HTML furnizat de script:

„http://www.w3.org/1999/xhtml”> > > Pagina stocată în cache > „text/html; charset=windows-1251” /> > > Această pagină este stocată în cache folosind PHP „http://www.php.net/outcontrol”> Funcții de control a ieșirii > > >

Blocați tamponarea

O abordare simplificată memorează memoria tampon de ieșire ca o singură pagină. Cu toate acestea, această abordare vă răpește puterea reală pe care o oferă funcțiile PHP de gestionare a ieșirii pentru a îmbunătăți performanța site-ului dvs., variind durata de viață a conținutului dvs. în consecință.

Fără îndoială, unele părți ale paginii pe care le trimiteți vizitatorului dvs. se modifică foarte rar, cum ar fi antetul, meniul și subsolul. Cu toate acestea, alte părți, cum ar fi tabelele care conțin discuții pe forum, se pot schimba destul de frecvent. Buffer-ul de ieșire poate fi folosit pentru a stoca în cache secțiuni ale unei pagini în fișiere separate, apoi pentru a construi pagina din ele - o soluție care elimină nevoia de interogări repetate la baza de date, bucle while etc. Puteți atribui fiecărui bloc de pagină o dată de expirare după care fișierul cache este recreat sau puteți include și un mecanism în aplicația dvs. care va șterge fișierul cache ori de câte ori conținutul stocat în acesta este modificat.

Iată un exemplu care demonstrează acest principiu:

Exemplul 5.3. 3.php (pornire)

/** * Intrare fișier cache * @param șir conținut – conținut tampon * @param șir nume fișier – numele fișierului folosit la crearea fișierului cache * @return void */ funcția writeCache($conținut , $nume fișier ) ( $fp = fopen ("./cache/" . $nume fișier , "w" ) ; fwrite ($fp , $conținut ) ; fclose ($fp ) ; ) /** * Verificarea fișierelor cache * @param șir nume fișier – numele fișierului cache care este verificat * @param int expirare – „vârsta” maximă a fișierului în secunde * @return conținuturi cache mixte sau false */ funcția readCache($filename , $expiry ) ( dacă (fișier_există ("./cache/" . $filename ) ) ) (dacă ((time () - $expiry ) > filemtime ("./cache/" . $filename ) ) ) return FALSE ; $cache = fișier ("./cache/" . $filename ) ;

Primele două funcții pe care le-am definit sunt scrie cacheȘi readCache, sunt folosite, respectiv, pentru a crea fișiere cache și a verifica existența acestora. Funcția writeCache primește datele pentru a stoca în cache în primul său argument și numele fișierului de utilizat la crearea fișierului cache. Funcția readCache primește numele fișierului cache ca prim parametru, împreună cu timpul în secunde după care fișierul cache ar trebui să fie considerat învechit. Dacă găsește fișierul cache valid, scriptul va returna conținutul său, în caz contrar va returna FALSE pentru a indica faptul că fișierul cache nu există sau este învechit.

În acest exemplu am folosit o abordare procedurală. Cu toate acestea, nu recomand să faceți acest lucru în practică, deoarece va ajunge într-un cod foarte dezordonat (vedeți soluțiile ulterioare pentru o alternativă mai bună) și va cauza probabil probleme de blocare a fișierelor (de exemplu, ce se întâmplă când cineva accesează memoria cache în timp ce acesta este în curs de actualizare?).

Să continuăm cu acest exemplu. Odată ce bufferingul de ieșire a început, începe procesarea. Scriptul apelează mai întâi readCache pentru a vedea dacă fișierul 3_header.cache există, conține antetul paginii - antetul HTML și începutul corpului. Folosim funcția de dată a PHP pentru a afișa ora la care pagina a fost generată efectiv, astfel încât veți vedea diferitele fișiere cache în acțiune atunci când pagina este redată.

Exemplul 5.4. 3.php (continuare)

// Porniți ieșirea în buffer ob_start(); // Prelucrare antet if (!$header = readCache("3_header.cache" , 604800 ) ) ( // Afișează antetul ?>„-//W3C//DTD XHTML 1.0 Strict//EN” „http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”> „http://www.w3.org/1999/xhtml”> Pagina stocată în cache bloc cu bloc „text/html; charset=windows-1251” /> Timp de creare a antetului:

Ce se întâmplă când fișierul cache nu este găsit? Un anumit conținut este scos și atribuit unei variabile folosind ob_get_contents, după care tamponul este șters de funcția ob_clean. Acest lucru ne permite să captăm ieșirea bucată cu bucată și să o potrivim cu fișierele cache individuale folosind writeCache. Titlul paginii este acum stocat ca un fișier care poate fi folosit fără intervenția noastră în reconstruirea paginii. Să ne întoarcem pentru o secundă la începutul declarației condiționale. Când am apelat readCache, i-am trecut o durată de viață cache de 604800 de secunde (o săptămână), readCache folosește timpul de modificare a fișierului cache pentru a determina dacă fișierul cache este încă valid.

Pentru conținutul (corpul) paginii vom folosi în continuare același proces. Cu toate acestea, de data aceasta când numim readCache vom folosi o durată de viață a cache-ului de cinci secunde, fișierul cache va fi modificat de fiecare dată când este „mai vechi” de 5 secunde:

Exemplul 5.5. 3.php (continuare)

// Procesează corpul paginii if (!$body = readCache("3_body.cache" , 5 ) ) ( echo „Timpul creării corpului:”. data ("H:i:s") . "
" ; $body = ob_get_contents () ; ob_clean () ; writeCache($body, "3_body.cache" ) ; )

Subsolul poate fi modificat efectiv în același mod ca și antetul. După aceasta, tamponarea de ieșire se oprește și este afișat conținutul a trei variabile care conțin date de pagină:

Exemplul 5.6. 3.php (sfârșit)

// Gestionează subsolul paginii if (!$footer = readCache("3_footer.cache" , 604800 ) ) ( ?> Timpul de creare a subsolului:
// opriți tamponarea ob_end_clean(); // Afișează conținutul paginii echo $header . $corp . $subsol ;

Rezultatul final arată cam așa:

Timp de creare a antetului: 17:10:42 Timpul de creare a corpului: 18:07:40 Timpul de creare a subsolului: 17:10:42

Antetul și subsolul sunt actualizate săptămânal, în timp ce corpul este modificat când este mai vechi de 5 secunde.

Diagrama bloc din Figura 5.1 rezumă metodologia blocării tampon.

Figura 5.1. Schema bloc a blocului de ieșire tampon

Tampoane imbricate

Puteți imbrica un buffer într-un altul practic la nesfârșit, apelând ob_start în mod repetat. Acest lucru poate fi util dacă aveți o mulțime de operațiuni care folosesc bufferul de ieșire, de exemplu unele care captează mesaje de eroare PHP, altele care se ocupă de stocarea în cache. Trebuie să vă asigurați că ob_end_flush sau ob_end_clean este apelat de fiecare dată când este utilizat ob_start.

Cum pot implementa un sistem simplu de stocare în cache pe partea serverului?

Acum că înțelegem ideile din spatele stocării tampon de ieșire, este timpul să ne uităm la modul în care putem pune acest proces în acțiune într-un mod ușor de întreținut. Pentru a face acest lucru, vom folosi puțin ajutor de la PEAR::CacheLite (versiunea 1.1 a fost folosită în exemplele de aici).

Cache_Lite

După cum am spus, în interesul de a face codul mai ușor de întreținut și de a avea un mecanism de cache fiabil, este înțelept să atribuiți responsabilitatea pentru logica cache-ului claselor în care aveți încredere. Cache_Lite este o bibliotecă de stocare în cache puternică, dar ușor de utilizat, care se ocupă de sarcini precum blocarea temporară a fișierelor cache, crearea și validarea acestora, gestionarea bufferului de ieșire și stocarea directă în cache a rezultatului unei funcții sau unei metode de clasă. Motivul principal pentru alegerea acestei biblioteci este integrarea relativ simplă a lui Cache_Lite într-o aplicație existentă, care necesită doar modificări minore ale codului.

Cache_Lite constă din trei clase principale. Prima este clasa de bază Cache_Lite, care este responsabilă numai pentru crearea și citirea fișierelor cache și nu tamponează ieșirea. Această clasă poate fi folosită singură în cazurile în care nu este nevoie să folosiți buffering de ieșire, cum ar fi atunci când salvați rezultatul analizării unui șablon PHP printr-un script. Exemplele prezentate aici nu folosesc clasa Cache_Lite direct și demonstrează utilizarea celorlalte două clase. Cache_Lite_Function este folosit pentru a apela o funcție sau o metodă de clasă și apoi pentru a stoca în cache rezultatele. Acest lucru poate fi util, de exemplu, pentru memorarea în cache a rezultatului unei interogări în My SQL?. Clasa Cache_Lite_Output folosește funcții de control al ieșirii PHP pentru a intercepta datele generate de un script și a le stoca în fișiere cache. Acest lucru vă permite să efectuați aceleași sarcini ca soluția anterioară.

Iată un exemplu care vă va arăta cum puteți utiliza Cache_Lite pentru a îndeplini sarcina pe care am descris-o în partea anterioară. Pentru a lua în considerare orice utilizare a Cache_Lite, trebuie mai întâi să o configuram - să creăm o matrice de parametri - care va determina comportamentul clasei. Le vom analiza mai detaliat mai jos, dar pentru moment, vă rugăm să rețineți că scriptul dvs. trebuie să aibă permisiuni de citire și scriere în directorul cacheDir.

Exemplul 5.7. 4.php (pornire)

// Conectați clasa de ieșire PEAR::Cache_Lite require_once "Cache/Lite/Output.php"; // Definiți setările pentru Cache_Lite$options = array ( "cacheDir" => "./cache/" , "writeControl" => "true" , ​​​​"readControl" => "true" , ​​​​"readControlType" => "md5" ) ; // Creați un obiect din clasa Cache_Lite_Output

Pentru fiecare parte a rezultatului scriptului pe care doriți să o păstrați în cache, trebuie să setați durata de viață a cache-ului în secunde. această dată determină cât timp să preiau datele din cache. După acest timp, datele din fișier vor fi actualizate. Apoi, apelăm metoda start(), disponibilă numai în clasa Cahce_Lite_Output, care permite stocarea în buffer de ieșire. Trecem 2 parametri metodei: primul este identificatorul fișierului cache, al doilea este grupul (tipul cache). Parametrul „grup” vă permite să combinați mai multe șabloane, acest lucru vă permite să efectuați acțiuni de grup, de exemplu, ștergerea tuturor fișierelor cache dintr-un grup. Odată ce rezultatul piesei de care avem nevoie este terminat, trebuie să apelăm metoda stop(). Această metodă va opri stocarea tampon și va salva conținutul tamponului într-un fișier.

Exemplul 5.8. 4.php (continuare)

// Setați durata de viață a cache-ului pentru această parte$cache ->setLifeTime (604800); // Începeți tamponarea pentru secțiunea numită antet // și puneți-l în grupul Static 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”> Exemplu PEAR::Cache_Lite „text/html; charset=windows-1251” />

Exemplu PEAR::Cache_Lite

Timp de creare a antetului:
// Opriți stocarea tampon și scrieți tamponul într-un fișier$cache ->end () ; )

Memorarea în cache a corpului principal al ieșirii (corpului) și a părții de jos (subsol) este similară cu memorarea în cache a antetului. Vă rugăm să rețineți că am setat din nou durata de viață a cache-ului pentru fiecare parte ulterioară.

Exemplul 5.9. 4.php (continuare)

$cache ->setLifeTime (5 ); if (!$cache ->start ("corp", "Dynamic")) ( ecou „Timpul creării corpului:”. data ("H:i:s") . "
" ; $cache ->end () ; ) $cache ->setLifeTime (604800) ; if (!$cache ->start ("footer", "Static") ) ( ?> Timp de creare de jos:
Sfârşit(); )

Când apelați această pagină pentru a vizualiza, Cache_Lite va crea următoarele fișiere în directorul cache:

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

Dacă solicitați aceeași pagină mai târziu, codul de mai sus vă va arăta conținutul acestor fișiere, desigur, dacă durata lor de viață nu a expirat încă.

  • Protejați fișierele din cache.
  • Asigurați-vă că directorul în care stocați fișierele cache nu este accesibil public. în caz contrar, vizitatorii site-ului dvs. vor putea face mai mult decât v-ați dori să facă.

Setări Cache_Lite

Când apelați Cache_Lite (sau oricare dintre subclasele sale, cum ar fi Cache_Lite_Output), există multe modalități de a-i controla comportamentul. Toți parametrii trebuie plasați într-o matrice și trecuți la constructor:

Exemplul 5.10. 4.php (sfârșit)

// Setați setările pentru Cache_Lite$options = array ( "cacheDir" => "./cache/" , "writeControl" => TRUE , "readControl" => TRUE , "readControlType" => "md5" ) ; // Creați un obiect Cache_Lite_Output$cache = new Cache_Lite_Output($opțiuni) ;

În versiunea curentă a clasei (1.1), sunt disponibile următoarele setări:

  • cacheDir – Acesta este directorul în care vor fi plasate fișierele cache. Valoarea implicită este directorul în care este executat scriptul.
  • cache – Această opțiune activează sau dezactivează capabilitățile Cache_Lite. De exemplu, dacă aveți o mulțime de solicitări către Cache_Lite și în timpul depanării doriți să dezactivați stocarea în cache, setați-o la FALSE. Valoarea implicită este TRUE.
  • durata de viață – Acest parametru conține durata de viață implicită a cache-ului (în secunde). Puteți modifica valoarea apelând metoda setLifeTime(). Valoarea implicită este 3600 (o oră).
  • fileNameProtection – Dacă această opțiune este activată, Chache_Lite va folosi codificarea MD5 pentru a genera numele fișierului cache. Acest lucru vă permite să utilizați orice caractere în numele fișierelor și grupurilor cache, chiar și a celor interzise de sistemul de fișiere. Această setare trebuie să fie activată când utilizați Cache_Lite_Function. Valoarea implicită este TRUE (activată).
  • fileLocking – Acest parametru activează mecanismele de blocare a unui fișier cache în timp ce datele sunt scrise în el. Valoarea implicită este TRUE (activată).
  • writeControl – Verifică dacă fișierul cache a fost scris corect imediat după terminarea scrierii. În cazul unei erori, aruncă PEAR:Error. Această caracteristică permite scriptului să suprascrie din nou fișierul cache, dar îl încetinește. Valoarea implicită este TRUE (activată).
  • readControl – Înainte de a citi un fișier cache, verifică dacă este deteriorat. Cache_Lite plasează o valoare a lungimii fișierului în fișier care poate fi folosită pentru a-i monitoriza integritatea. Există, de asemenea, un mecanism alternativ pentru verificarea integrității fișierului. Este activat de parametrul readControlType. Aceste mecanisme încetinesc oarecum viteza, dar vă ajută să vă asigurați că utilizatorii văd o pagină necoruptă. valoarea implicită este TRUE (activată).
  • readControlType – Acest parametru determină tipul mecanismului de citire a fișierului cache. Mecanisme disponibile: verificare ciclică de redundanță („crc32” - valoare implicită) - folosește funcția PHP crc32, hash „MD5” - folosește funcția PHP md5, sau o verificare simplă a lungimii - „strlen”. Vă rugăm să rețineți că acest mecanism nu este destinat să protejeze fișierele cache împotriva accesului direct de către utilizatori neautorizați. Aceasta este doar o modalitate de a determina dacă un fișier este corupt sau nu.

pearErrorMode – Activează metoda PEAR pentru returnarea erorilor. Valoarea implicită este CACHE_LITE_PEAR_RETURN – returnează obiectul /#c#?PEAR::Error.

  • memoryCaching – Dacă această opțiune este activată, de fiecare dată când apelați memoria cache pentru a scrie într-un fișier, aceasta este scrisă în matricea Cache_Lite. saveMemoryCachingState și getMemoryCachingState sunt folosite pentru a accesa memoria cache stocată în memorie între cereri. Avantajul acestei metode este că conținutul cache-ului poate fi stocat într-un singur fișier, reducând numărul de cicluri de citire/scriere pe disc. Cache-ul este restaurat direct într-o matrice pe care scriptul dumneavoastră o poate accesa. În exemplele noastre vom folosi mecanismul obișnuit Cache_Lite, dar poate doriți să experimentați cu această opțiune mai târziu dacă aveți un site foarte mare. Implicit este TRUE (dezactivat).
  • onlyMemoryCaching – Dacă activați această opțiune, va fi utilizat doar mecanismul de cache în memorie. Implicit este TRUE (dezactivat).

memoryCachingLimit – Acest parametru specifică limita numărului de fișiere cache care pot fi stocate într-o matrice în memorie. Cu cât numărul de fișiere este mai mare, cu atât mai multă memorie va fi consumată. Prin urmare, definirea unei limite este o idee foarte bună. Desigur, acest lucru nu afectează dimensiunea fișierului cache, deoarece unul sau două fișiere masive nu vor crea probleme. valoarea implicită este 1000.

Golirea memoriei cache

Cahce_Lite conține un mecanism de succes pentru determinarea duratei de viață a fișierelor cache, care creează o bază bună pentru siguranța fișierelor dvs. și pentru actualizarea lor în timp util. Cu toate acestea, există momente când trebuie să actualizați imediat fișierul cache. Pentru astfel de cazuri, există metode remove() și clean(). Metoda remove() este concepută pentru a elimina un anumit fișier cache. necesită ID-ul cache-ului și numele grupului căruia îi aparține fișierul. Următorul exemplu va șterge fișierul cache al corpului din exemplul anterior:

$cache ->eliminare ("corp" , "Dinamic" );

Metoda clean() ne permite să ștergem toate fișierele din directorul nostru dacă o numim fără parametri. Dacă treceți numele grupului ca parametru, toate fișierele incluse în acest grup vor fi șterse. Dacă dorim să eliminăm antetul și partea de jos, atunci trebuie să trimitem comenzi similare cu acestea:

$cache ->clean ("Static" );

Metodele remove() și clean() trebuie în mod evident apelate ca răspuns la evenimentele din cadrul aplicației. De exemplu, aveți un forum, probabil ar trebui să ștergeți fișierul cache dacă vreun utilizator postează un mesaj nou. Deși această soluție arată bine, poate implica unele modificări de cod. Dacă aveți un script principal care se conectează la fiecare pagină a aplicației pe care o poate vizualiza un vizitator, puteți pur și simplu urmăriți evenimentele care apar, cum ar fi variabila $_GET["newPost"], eliminând fișierele cache necesare. Acest lucru vă va permite să creați un mecanism centralizat de gestionare a memoriei cache. ai putea chiar include acest cod in php.ini (vezi descrierea setarii auto_prepend_file).

Memorarea în cache a apelurilor de funcție

În Capitolul 2, XML, am analizat accesul de la distanță la serviciile web folosind SOAP și XML-RPC. Deoarece serviciile web sunt accesibile prin rețea, este adesea o idee bună să memorați rezultatul în cache, astfel încât să poată fi executat local, mai degrabă decât să repetați aceeași interogare lentă din nou și din nou. În cel mai simplu caz, am putea folosi sesiuni PHP, pe care le-am tratat în acel capitol, dar întrucât această soluție se bazează pe frecvența vizitatorilor, deschiderea unei cereri pentru fiecare vizitator ar fi totuși lentă. În astfel de cazuri, Cache_Lite poate fi foarte util.

  • PEAR folosește Cache_Lite
  • Programul de instalare PEAR Web (citiți Anexa D, care lucrează cu PEAR) utilizează Cache_Lite pentru a stoca în cache cererile XML-RPC trimise către serverul Web PEAR.

În secțiunea numită „Cum consum serviciile SOAP Web cu PHP?”, am scris un client pentru a servi un serviciu web SOAP pe baza fișierului său WSDL; Acest serviciu oferă informații despre vreme tuturor aeroporturilor din lume. Iată codul care primește date de la serverul de la distanță:

$țări = $stationInfo ->listCountries () ;

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

În ambele cazuri, aceste apeluri corespund unei solicitări de date prin rețea. Folosind Cache_Lite, am putea stoca în cache datele returnate de serviciu și le putem reutiliza. Acest lucru ar evita conexiunile suplimentare inutile la rețea și ar crește semnificativ viteza de execuție. Vă rugăm să rețineți că aici ne uităm doar la codul legat de subiectul nostru. Mai întâi activăm Cache_Lite_Function:

Exemplul 5.11. 5.php (pornire)

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

Exemplul 5.12. 5.php (continuare)

// Setați parametrii pentru Cache_Lite_Function // AVERTISMENT: fileNameProtection = TRUE!$options = array ( "cacheDir" => "./cache/" , "fileNameProtection" => TRUE , "writeControl" => TRUE , "readControl" => TRUE , "readControlType" => "strlen" , "defaultGroup" => "SAPUN" ); // Creați un obiect din clasa Cache_Lite_Function$cache = new Cache_Lite_Function($opțiuni) ;

Este important ca parametrul fileNameProtection să fie setat la TRUE. Aceasta este valoarea implicită, dar am setat-o ​​manual în mod special pentru a-i sublinia semnificația. Setarea acestei opțiuni la FALSE va avea ca rezultat un nume de fișier nevalid, astfel încât stocarea în cache nu va avea loc.

Exemplul 5.13. 5.php (continuare)

$țări = $cache ->call ( "stationInfo->listCountries" );

Exemplul 5.14. 5.php (sfârșit)

$țara = $cache ->apel ( „stationInfo->searchByCountry”,$_GET [„țara” ]) ;

Dacă o solicitare este făcută pentru prima dată, Cache_Lite_Function stochează rezultatele ca o matrice serializată într-un fișier cache (nu trebuie să vă faceți griji pentru asta) și acest fișier va fi folosit pentru cererile viitoare până la expirarea duratei sale de viață. setLifeTime poate fi folosit pentru a determina cât timp va dura un fișier cache înainte de a-și actualiza informațiile. Valoarea implicită este 1 oră (3600 secunde).

În general, Cache_Lite oferă un sistem unic, ușor de utilizat pentru a rezolva orice probleme legate de stocarea în cache. Deoarece următorul nivel este site-urile cu trafic deosebit de mare, ar trebui să explorați PEAR::Cache, care este fratele mai mare al lui Cache_Lite. De asemenea, oferă capabilități îmbunătățite de stocare în cache, cum ar fi stocarea în memoria cache partajată ca alternativă la stocarea în cache a fișierelor sau extensia PHP Msession pentru a ajuta la stocarea datelor într-o sesiune echilibrată, ceea ce este util în special în serverele WEB echilibrate. Voi oferi alte materiale despre PEAR::Cache la sfârșitul acestui articol. Cache_Lite, însă, oferă mai mult decât suficiente funcții și răspunde nevoilor majorității site-urilor.

Cum pot gestiona stocarea în cache pe partea client folosind PHP?

Acum că ne-am uitat la opțiunile pentru suprascrierea cache-ului pe partea client și cum poate fi implementată cache-ul pe partea client, este timpul să ne uităm la un mecanism care ne va permite să controlăm cache-ul pe partea client folosind PHP. Această abordare va funcționa numai dacă utilizați PHP cu un server Apache, deoarece vom folosi funcția getallheaders pentru a obține anteturile trimise de browser. această funcție funcționează numai în Apache.

Nume noi de funcții

Dacă utilizați PHP 4.3.0 cu Apache, anteturile HTTP sunt disponibile prin funcțiile apache_request_headers și apache_response_headers. Funcția getallheaders a devenit un alias pentru noua funcție apache_request_headers.

Mecanismul de lucru cu memoria cache a browserului web este din nou HTTP. Multe anteturi sunt implicate în instruirea browserelor web și serverelor proxy să memoreze în cache independent o pagină, situație complicată de faptul că unele dintre ele sunt disponibile numai cu HTTP 1.1.

Verificarea antetelor HTTP în browser

Un instrument simplu, dar foarte convenabil pentru verificarea antetelor cererilor și răspunsurilor este Live Http Headers? – supliment pentru browserul Mozilla. Este important să știți exact ce anteturi trimite scriptul dvs., mai ales când aveți de-a face cu anteturi de cache HTTP.

Pentru simplitate, vom lua în considerare doar anteturile de cache HTTP 1.0, și anume Expires, Last-Modified și If-Modified-Since, precum și codul de stare HTTP 304 (Nemodificat).

Alte anteturi disponibile cu HTTP 1.1, cum ar fi Cache-Control și ETag, sunt menite să ofere un mecanism avansat care poate fi utilizat împreună cu starea sesiunii web, cu alte cuvinte, versiunea unei anumite pagini afișată unui vizitator neautorizat poate fi semnificativ diferit de cel afișat pentru un utilizator autorizat. Antetele HTTP 1.1 au fost adăugate inițial pentru a permite ca astfel de pagini să fie stocate în cache.

Termenul de valabilitate al paginii

Cel mai ușor antet de utilizat este antetul Expire, care stabilește o dată (posibil în viitor) când pagina va expira. Până în acest moment, browserului web îi este permis să utilizeze versiunea stocată în cache a paginii.

Exemplul 5.15. 6.php

/** * Trimite antetul Expires HTTP 1.0. * @param int numărul de secunde până la expirarea timpului */ function setExpires($expires) ( antet ("Expire: " . gmdate ("D, d M Y H:i:s" , ora () + $expires ) . "GMT" ) ; ) // Setați antetul pentru timpul de expirare Expiras setExpires(10) ; // Afișează ecou „Această pagină se va autodistruge în 10 secunde
"
; ecou "Acum". gmdate("H:i:s") . " GMT
" ; echo """>Vizualizare din nou
" ;

Funcția setExpires trimite un antet HTTP Expires cu o oră viitoare specificată în secunde. Exemplul de mai sus arată ora actuală GMT și afișează un link care vă permite să reveniți la pagină. Folosind butonul Reîmprospătare al browserului, îi puteți spune browserului că doriți să-și reîmprospăteze memoria cache. Folosind link-ul veți vedea că ora se schimbă doar o dată la 10 secunde.

Date și ore în HTTP

Datele în HTTP sunt întotdeauna calculate în raport cu Greenwich Mean Time (GMT). Funcția PHP gmdate este exact aceeași funcție cu data, cu excepția faptului că compensează automat GMT în funcție de ceasul sistemului și de setările de regiune ale serverului dvs.

Când browserul întâlnește antetul Expires, acesta memorează pagina în cache. Toate solicitările ulterioare pentru pagină făcute înainte de expirarea specificată folosesc versiunea stocată în cache a paginii și nu se fac cereri către serverul web.

Antetul Expires este în mare parte simplu de implementat, dar în majoritatea cazurilor, cu excepția cazului în care sunteți o persoană foarte organizată, nu aveți de unde să știți exact când o anumită pagină de pe site-ul dvs. este actualizată. Deoarece browserul va contacta serverul numai după ce pagina a devenit învechită, nu există nicio modalitate de a-i spune browserului că o pagină din memoria cache a acesteia este învechită. De asemenea, pierzi puțin trafic către site-ul tău web, deoarece browserul nu contactează serverul atunci când solicită o pagină în cache.

Ora de schimbare a paginii

Este mai practic să folosiți anteturile Last-Modified și If-Modified-Since disponibile în HTTP 1.0. Cunoscut din punct de vedere tehnic ca efectuarea unei cereri GET condiționate, returnați orice conținut pe baza condiției de antet a cererii If-Modified-Since.

Când utilizați această metodă, trebuie să trimiteți un antet Last-Modified de fiecare dată când este accesat scriptul PHP. Data viitoare când browserul solicită pagina, va trimite un antet If-Modified-Since care conține timpul pe care scriptul dumneavoastră îl poate folosi pentru a determina dacă pagina a fost actualizată de la ultima solicitare. Dacă nu este cazul, scriptul dvs. trimite un cod de stare HTTP 304 pentru a indica faptul că pagina nu s-a schimbat, fără a imprima conținutul paginii.

Cel mai simplu exemplu de GET condiționat este destul de complicat, un instrument destul de convenabil pentru a arăta cum funcționează este PEAR::Cache_Lite. Cu toate acestea, acesta nu ar trebui considerat un exemplu de stocare în cache a serverului, ci pur și simplu implică modificarea periodică a unui fișier.

Exemplul 5.16. 7.php (pornire)

// Conectați PEAR::Cache_Lite require_once "Cache/Lite.php"; // Definiți setările Cache_Lite$options = array ( "cacheDir" => "./cache/" ); // Inițializați Cache_Lite$cache = new Cache_Lite($opțiuni) ; // Câteva date false de stocat$id = "MyCache" ; // Inițializați memoria cache dacă pagina este solicitată pentru prima dată if (!$cache ->get ($id) ) ( $cache ->save ("Dummy", $id) ; ) // Randomizer...$aleatoriu = tablou (0 , 1 , 1 ) ; amestecare ($aleatorie); // Actualizare aleatorie a memoriei cache if ($aleatoriu [ 0 ] == 0 ) ( $cache ->salvează ( "Dummy" , $id ) ; ) // Obține ora ultimei modificări a fișierului cache$lastModified = filemtime ($cache ->_file) ; antet ("Last-Modified: " . gmdate ("D, d M Y H:i:s" , $lastModified ). " GMT" ) ; < v6 отдаёт их неправильно) $modificatDe când = 0 ; ) dacă ($lastModified<= $modifiedSince ) { header ("HTTP/1.1 304 Not Modified" ) ; exit () ; } echo "Сейчас " . gmdate ("H:i:s" ) . "GMT
"
; echo """>Actualizare
" ;

Amintiți-vă să utilizați linkul Reîmprospătare când rulați acest exemplu (făcând clic pe Reîmprospătare va șterge de obicei memoria cache a browserului). Dacă faceți clic pe link în mod repetat, eventual cache-ul va fi modificat, browserul dumneavoastră va elimina versiunea din cache și va stoca noua pagină furnizată de PHP în ea.

În exemplul de mai sus, am folosit PEAR::Cache_Lite pentru a crea un fișier cache modificat aleatoriu. Am stabilit timpul de modificare a fișierului cache cu această linie:

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

Tehnic vorbind, acesta este un hack deoarece variabila $_file a clasei PEAR::Cache_Lite ar trebui să fie privată. Cu toate acestea, suntem forțați să-l folosim pentru a obține numele fișierului cache și pentru a afla timpul de modificare a acestuia.

Apoi, folosind timpul de modificare a fișierului cache, trimitem antetul Last-Modified. Trebuie să trimitem acest lucru pentru fiecare pagină difuzată pentru a forța browserul să ne trimită un antet If-Modified-Since la fiecare solicitare.

// Emiteți antetul HTTP Ultima modificare antet ("Last-Modified: " . gmdate ("D, d M Y H:i:s" , $lastModified ). " GMT" ) ;

Folosind funcția getallheaders ne asigurăm că primim toate anteturile primite din PHP ca o matrice. Apoi trebuie să verificăm dacă antetul If-Modified-Since există, dacă există, trebuie să ne ocupăm de cazul special al versiunilor mai vechi de Mozilla (sub versiunea 6) care a adăugat un câmp suplimentar la antetul If-Modified- la sfârşitul (abaterea de la specificaţie). Folosind funcția PHP strtotime, obținem marcajul de timp al datei transmise de browser. Dacă nu există un astfel de antet, atribuim un marcaj temporal de zero, forțând astfel PHP să ofere vizitatorului cea mai recentă versiune a paginii.

// Obține antetele cererilor client - numai Apache$request = getallheaders(); if (isset ($request [ "Dacă-Modificat-De când" ] ) ) ( // Split If-Modified-Since (Netscape< v6 отдаёт их неправильно) $modifiedInce = explode (";" , $request [ "If-Modified-Since" ] ); // Convertiți cererea If-Modified-Since a clientului într-un timestamp$modifiedInce = strtotime ($modifiedInce [ 0 ] ) ; ) altfel ( // Setați ora de modificare la zero$modificatDe când = 0 ; )

În cele din urmă, verificăm dacă memoria cache a fost modificată de când vizitatorul a primit ultima dată această pagină. Dacă nu este cazul, pur și simplu trimitem un răspuns Not Modified în antet și oprim executarea scriptului, fără a încărca link-ul de date și a economisi timp CPU prin instruirea browserului să afișeze o versiune în cache a paginii.

// Comparați timpul ultimei modificări de conținut cu memoria cache a clientului dacă ($lastModified<= $modifiedSince ) { // Descarcă canalul de transmisie a datelor! header("HTTP/1.1 304 Nemodificat"); Ieșire(); )

Dacă combinați ultima abordare a timpului modificat cu o valoare a timpului care este deja disponibilă în aplicația dvs. (de exemplu, ora celui mai recent articol de știri sau timpul de expirare din sistemul de cache pe server pe care l-am văzut în ultima soluție) , puteți profita de memoria cache a browserului web și puteți ușura canalul de transmitere a datelor, economisind traficul de informații de pe site-ul dvs. acolo unde este posibil și îmbunătățind performanța percepută a acestuia.

Fiți atenți când testați orice stocare în cache realizată în acest stil, dacă o faceți incorect, puteți determina vizitatorii dvs. să aibă întotdeauna copii învechite ale site-ului dvs.

Link-uri suplimentare

  • Solicitare GET cu condiție (GET condiționat)
  • Urmărirea conținutului pe site-uri dinamice

Cele mai bune articole pe această temă