Проста и ефективна PHP система за кеширане. WordPress Super Cache, задължителен WP плъгин

Кеширането на междинни данни е най-примитивният и в същото време най-полезният начин за оптимизация, при който не е нужно да се занимавате със сложни алгоритми или предварителна оптимизация. Ако възнамерявате да работите с PHP, трябва да сте наясно с доказаните методи и инструменти, необходими, за да накарате вашия сайт да лети.

Статични локални променливи

Бърз и ефективен начин за кеширане на резултатите от функция/метод е използването на статични локални променливи. Нека да разгледаме пример, който извършва сложни изчисления:

Сега всеки път, когато използвате функция в код, независимо от броя на извикванията, функцията ще извършва изчисления само веднъж.

Тази техника за кеширане е независима от външни разширения и се поддържа на ниво език. Тъй като статичните локални променливи са достъпни само във функцията, в която са дефинирани, актуализирането на кеша може да бъде проблематично. Обикновено това изисква предаване на някакъв вид булева променлива към $use_cache или използване на статични класови променливи вместо това.

Статичните променливи не се споделят между PHP процесии може да кешира само за кратко време - покривайки времето за изпълнение на скрипта. Добър кандидат е метод, който се извиква много пъти от множество места, например за съхраняване на потребителско състояние или резултат, който изисква голям обемматематически изчисления.

Същата функционалност може да се приложи с помощта на глобални променливи, но това ще замърси глобалното пространство от имена и не се препоръчва.

Функции за споделена памет на APC

PHP е полукомпилиран език, което означава, че всеки скрипт се компилира не директно в машинен код, а в междинен код, известен като набор от кодове за операции (байт код). Тази стъпкакомпилацията консумира много ресурси на процесора и трябва да се изпълнява всеки път, когато се изпълнява скриптът. APC (Alternative PHP Cache) е разширение, което пропуска тази стъпка на компилация, като кешира кодовете за операции в паметта.

Въпреки че основната цел на APC обикновено се счита за функционалност за кеширане на опкод, разширението включва и някои допълнителни функции за достъп до паметта.

Сега предимството на този подход е очевидно - това е използването на споделена памет. Този тип памет се споделя между различни процеси/нишки и, за разлика от статичните променливи, данните, които се кешират по този начин, ще съществуват в множество заявки.

За да обезсилите кеш, можете да използвате стойности за време на живот (TTL), както в примера по-горе, или следните функции:

Други бележки относно поддръжката на споделена памет в APC:

В конфигурационния файл INI има директива за ограничаване на размера на кеша. С подходящи TTL стойности това осигурява възможност за приоритизиране на кеширани данни, където, ако бъде достигнат лимитът на паметта, изтеклите/старите стойности ще бъдат извадени от кеша.

От гледна точка на производителността, статичните променливи винаги ще бъдат по-бързи от функциите apc_fetch/apc_store, тъй като достъпът до споделената памет трябва да бъде заключен и синхронизиран, за да се предотвратят конфликти.

APC е доста популярно разширение и се поддържа от major PHP разработчиции (много вероятно) ще бъде в комплект с PHP 5.4.

Memcached за големи разпределени кешове

След като даден сайт започне да получава много посещения, в крайна сметка се превръща в задача за разпределяне на натоварването между различни машини. В резултат на това обикновено трябва да преместите PHP между множество сървъри за приложения. Ако сте използвали APC кеширане преди - всеки сървър на приложения вече има отделен и излишен кеш.

Memcached от друга страна е разпределена услуга за съхраняване на данни за ключ-стойност. Разширението може да бъде внедрено на отделен специализиран сървър или в същия стек на PHP приложение. Важно е да се разбере, че няма синхронизация/репликация между множество Memcached сървъри и те не знаят нищо един за друг. Действителният сървър, който ще се използва за съхранение, се избира от страна на клиента с помощта на алгоритъм за хеширане, базиран на предоставените „ключови“ данни. Ето защо, за разлика от APC, кешираните данни не се дублират между различни машини и паметта се използва по-добре за големи разпределени приложения.

API е много подобен на функционалността на споделената памет в APC. Същият пример с обмен на валута, реализиран с използвайки PHPРазширения на Memcache:

Актуализирането на кеша е същото като в APC - използвайки TTL функционалност или набор от функции.

Локалният APC кеш винаги ще бъде по-голям бърз методв сравнение с Memcached.

Винаги има закъснения в мрежата, когато клиентът трябва да комуникира с бекенд услугата чрез специален текстов протокол.

Таблици на база данни в RAM

Въпреки че не са специфични за PHP, много системи за управление на бази данни имат реализация на таблица в паметта. Данните, съхранявани в такива таблици, не се запазват между рестартирането на сървъра, гарантирано се съдържат в паметта и никога не се извеждат на диск. Това означава по-бърз достъп до записите, което ги прави подходящи за кеширане на данни.

MySQL предоставя таблици в паметта в подсистемата за съхранение MEMORY. Въпреки че данните ще бъдат изчистени след рестартиране на сървъра, схемите на таблиците ще бъдат запазени:

CREATE TABLE test (...) ENGINE = ПАМЕТ

PostgreSQL има временни таблици, които съществуват само по време на сесия; за да се кешират данни във временна таблица, трябва да се поддържа постоянна връзка с базата данни.

CREATE TEMPORARY TABLE test (...)

В SQLite можете да създадете цяла база данни в паметта, но със същите ограничения като в PostgreSQL - данните ще съществуват само по време на сесията и ще трябва да използвате постоянни връзкиза да ги поддържате между множество заявки.

И така, какво можете да направите с таблица в RAM? Въпреки че такава маса никога няма да съществува по-бърз достъпкъм данни ключ-стойност в APC/Memcached, получавате силата на SQL. Кешираните данни могат да бъдат филтрирани, подредени, групирани и дори обединени с други данни в таблици.

Обикновен файлов кеш

Плоският файлов кеш трябва да бъде алтернатива на методите, споменати по-горе, и трябва да се използва само когато системата няма необходимите разширения или въпросните данни не могат да бъдат съхранени в паметта (напр. поради размера)

Тъй като кеширането се прави, за да се подобри производителността, а оптимизирането на производителността е резултат от висока едновременност - винаги трябва да се използва заключване на файлове, за да се предотвратят условия на състезание за четене/запис:

В добрите стари времена, когато създаването на уебсайтове беше толкова просто, колкото да напишете няколко HTML-страници, изпращането на уеб страници към браузъра е просто изпращане на файл от уеб сървъра. Посетителите на сайта можеха да видят тези малки, само текстови страници почти мигновено (с изключение на потребителите на бавни модеми). След като страницата е заредена, браузърът я кешира някъде локален компютъртака че ако страницата бъде поискана отново, можете да я вземете локална версияот кеша, само изпращане кратко исканеза да се уверите, че страницата на сървъра не е била модифицирана. Заявките бяха обработени бързо и възможно най-ефективно и всички бяха доволни (с изключение на тези, които използват модеми с 9600 бода).

Външен вид динамични уеб страниципромени нещата към по-лошо, ефективно „счупвайки“ този модел на обслужване на уеб страници поради наличието на два проблема:

  • Когато сървърът получи заявка за динамична уеб страница, се извършва някаква междинна обработка, например парсване на скрипта от двигателя PHPкойто трябва да бъде завършен. Благодарение на това получаваме забавяне, преди уеб сървърът да започне да изпраща изход към браузъра. За прости PHP-script това не е от съществено значение, но за повече комплексно приложениедвигател PHPможе да отнеме много стъпки, преди страницата да е готова за изпращане. Тези допълнителни действияводят до забележимо забавяне между потребителските заявки и действителното показване на страниците в техните браузъри.
  • Типичен уеб сървър, като Apache, използва времето за модификация на файла, за да каже правилно на уеб браузъра състоянието на кеша на исканата страница. Всъщност за динамични уеб страници PHP-скриптът може да се променя само от време на време, докато съдържанието, което показва, евентуално разположено в база данни, се променя често. Уеб сървърът няма начин да знае, че има промени в базата данни, но не изпраща последната дата на модификация. Ако клиентът (браузърът) не получи никаква индикация за това колко време данните са правилни, той приема, че трябва да поиска нова страница следващия път. Уеб сървърът винаги ще отговаря с актуализирана версия на страницата, независимо дали данните са променени. За да избегнат този недостатък, повечето уеб разработчици използват мета тагове или HTTP- заглавки, за да кажете на браузъра никога да не използва кешираната версия на страницата. Това обаче отрича естествената способност на уеб браузъра да кешира уеб страници и има някои съществени недостатъци. Например, съдържанието на динамична страница може да се променя веднъж на ден, така че ползата от това, че браузърът кешира страницата дори за 24 часа, е очевидна.
  • Обикновено за малки PHP приложения е напълно възможно да пренебрегнете съществуването на тези проблеми, но с нарастването на сложността и трафика на вашия сайт може да срещнете проблеми. И двата проблема обаче могат да бъдат разрешени, първият чрез кеширане от страна на сървъра, вторият чрез управление на кеширането от страна на клиента от вашето приложение. Подходът, който ще предприемете за решаване на проблемите, ще зависи от вашето приложение, но в тази глава ще видим как можете да разрешите и двата проблема с помощта на PHP и някои библиотечни класове КРУША.

    Как да попреча на браузърите да кешират страница?

    Преди да разгледаме техниките за кеширане на клиенти и сървъри, първо трябва да разберем как да попречим на уеб браузърите (и прокси сървърите) да кешират страници на първо място. Основният начин за постигане на това е използването на HTML мета тагове:

    Като вмъкнете минала дата в мета тага Expires, казвате на браузъра, че кешираното копие на страницата винаги е остаряло. Това означава, че браузърът никога не трябва да кешира страницата. Мета таг Pragma: no-cache е доста добре поддържана конвенция, която повечето уеб браузъри следват. След като открият този маркер, те обикновено не кешират страницата (въпреки че няма гаранция, това е просто конвенция).

    Това звучи добре, но има два проблема с използването на мета тагове:

  • Ако маркерът не е съществувал, когато страницата е била заявена за първи път от браузъра, но се появява по-късно (например сте модифицирали файла за включване pageheader.php, който е заглавката на всяка уеб страница), браузърът ще остане в блажено неведение и ще използва своите кеширано копие на оригинала.
  • Прокси сървъри, които кешират уеб страници, като споделени ISP, изобщо няма да разглежда директно съдържанието HTML-документ. Вместо това те разчитат само на уеб сървъра, от който идват документите, и на протокола HTTP. С други думи, уеб браузърът може да мисли, че не трябва да кешира страницата, но прокси сървърът между браузъра и вашия уеб сървър вероятно не знае това - и ще продължи да изпраща същата, вече остаряла, страница на клиента .
  • Най-добрият подход е да използвате директно протокола HTTPизползвайки функцията PHP header(), еквивалентна на двата мета тагове по-горе:

    Можем да отидем една крачка напред, като използваме заглавката Cache-Control, която е съвместима с поддържаните браузъри HTTP 1.1:

    Header("Изтича до: Mon, 26 Jul 1997 05:00:00 GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", FALSE); заглавие ("Pragma: без кеш");

    Това гарантира, че нито един уеб браузър или междинен прокси сървър не кешира страницата, така че посетителите винаги получават възможно най-доброто изживяване. най-новата версиясъдържание. Всъщност първият хедър трябва да е самостоятелен, това най-добрият начинуверете се, че страницата не е кеширана. За по-голяма сигурност бяха добавени хедърите Cache-Control и Pragma. Въпреки че не работят във всички браузъри или проксита, те ще уловят някои случаи, в които Expires не работи според очакванията (например, ако датата на компютъра на клиента е зададена неправилно).

    Разбира се, пълното избягване на кеширането ни поставя пред проблемите, които обсъдихме в началото на тази глава. Сега ще разгледаме решаването на тези проблеми.

    Internet Explorer и кеширане на файлове за изтегляне

    Ако при обслужване изтегляне на файл PHP-скриптът използва заглавки като Content-Disposition: attachment, filename=myFile.pdf или Content-Disposition: inline, filename=myFile.pdf, с които ще имате проблеми Internet Explorer’om, ако кажете на браузъра да не кешира страницата.

    Internet Explorerобработва изтеглянията по доста необичаен начин, като прави две заявки към уебсайта. Първата заявка изтегля файла и го съхранява в кеша, докато не бъде направена втората заявка (без да съхранява отговора). Тази заявка задейства процеса на прехвърляне на файла до крайния потребител според типа на файла (например стартира Acrobat Readerако файлът е PDF-документ). Това означава, че ако сте изпратили заглавки, които пречат на браузъра да кешира страницата, Internet Explorerще изтрие файла между първата и втората заявка, което ще доведе до краен потребителняма да получи нищо. Ако файлът, който давате PHP-скрипт не се променя, едно от най-простите решения би било да се премахнат заглавките „забрана за кеширане“ от скрипта.

    Ако файлът, който се изтегля, се променя редовно (т.е. искате браузърът да изтегли най-новата версия), трябва да използвате заглавката Last-Modified, която ще бъде разгледана по-късно в тази глава, и да се уверите, че времето за промяна между две последователни заявки не промяна. Трябва да направите това по начин, който не засяга потребителите на браузъри, които обработват правилно изтеглянията. Едно решение в този случай би било да съхраните файла на вашия уеб сървър и да предоставите проста връзка към него, позволявайки на уеб сървъра да докладва кеширащите заглавки вместо вас. Разбира се, това решение може да не е приемливо, ако се предполага оторизиран достъп до файла; това решение позволява директно зареждане на записания файл.

    Как мога да заснема данни от страната на сървъра за кеширане?

    Време е да разгледаме как можем да намалим забавянето с помощта на кеширане на изход от страна на сървъра. Общият подход е да започнете да изобразявате страницата както обикновено, да изпълнявате заявки към база данни и така нататък PHP. Въпреки това, преди да изпратим резултата до браузъра, ние го улавяме и запазваме готова страница, например във файла. При следващата заявка, PHP-скриптът първо проверява за наличието на кеширана версия на страницата. Ако съществува, скриптът изпраща кешираната версия на браузъра, като по този начин елиминира забавянето при повторното създаване на страницата.

    Няколко думи за кеширането с помощта на шаблони. Как да управлявам кеширането от страна на клиента? използвайки PHP?

    Време е да разгледаме механизъм, който ще ни позволи да контролираме кеша от страна на клиента чрез средства PHP. Този подход ще работи само ако използвате PHPвъв връзка със сървъра Apacheтъй като ще използваме функцията getallheaders(), за да получим заглавките, изпратени от браузъра. Тази функция работи само в Apache.

    Нови имена на функции

    Ако използвате PHP 4.3.0 s Apache HTTP заглавките са достъпни чрез функцията apache_request_headers() и apache_response_headers(). Функцията getallheaders() се превърна в псевдоним на новата функция apache_request_headers().

    Отново е механизмът за работа с кеша на уеб браузъра HTTP. Много заглавки участват в инструктиране на уеб браузъри и прокси сървъри да кешират независимо страница, ситуация, усложнена от факта, че някои от тях са достъпни само от HTTP 1.1.

    Проверка на HTTP заглавките във вашия браузър

    Просто, но много удобен инструментза проверка на заглавките на заявката и отговора е LiveHttpHeaders– добавка за браузър Mozilla. Необходимо е да знаете точно какви хедъри изпраща вашият скрипт, особено когато имате работа с кеширащи хедъри HTTP.

    За простота ще разгледаме само заглавките за кеширане на HTTP 1.0, а именно Expires, Last-Modified и If-Modified-Since, както и HTTP 304 (непроменен) код на състоянието.

    Други заглавия, достъпни от HTTP 1.1, като Cache-Control и ETag, са предназначени да предоставят усъвършенстван механизъм, който може да се използва във връзка със състоянието на уеб сесията, с други думи, версията на дадена страница, показана на неупълномощен посетител, може да бъде значително различна от показаната на оторизиран потребител. Заглавия HTTP 1.1 първоначално бяха добавени, за да позволят такива страници да бъдат кеширани.

    Изтичане на жизнения цикъл на страницата

    Най-лесният за използване заглавка е заглавката Expire, която задава дата (вероятно в бъдеще), когато страницата ще изтече. До този момент на уеб браузъра е разрешено да използва кешираната версия на страницата.

    Пример 7. 6.php

    Функцията setExpires изпраща заглавката HTTPИзтича с бъдещо време, посочено в секунди. Горният пример показва текущо време GMT и показва връзка, която ви позволява да отидете отново на страницата. С помощта на бутона Refresh на вашия браузър можете да кажете на браузъра, че искате да обнови кеша. Използвайки връзката, ще видите, че времето се променя само веднъж на всеки 10 секунди.

    Дати и часове в HTTP

    Датите в HTTP винаги се изчисляват спрямо средното време по Гринуич (GMT). PHP функция gmdate() е точно същата функция като date(), с изключение на това, че автоматично компенсира GMT времето въз основа на системния часовник и регионалните настройки на вашия сървър.

    Когато браузърът срещне заглавката Expires, той кешира страницата. Всички последващи заявки за страници, направени преди указаното време на изтичане, използват кешираната версия на страницата и не се правят заявки към уеб сървъра.

    Заглавката Expires е най-вече лесна за прилагане, но в повечето случаи, освен ако не сте високо организиран човек, няма начин да знаете точно кога дадена страница на вашия сайт е актуализирана. Тъй като браузърът ще се свърже със сървъра само след като страницата е остаряла, няма начин да кажете на браузъра, че страница в неговия кеш е остаряла. Освен това губите част от трафика към уебсайта си, тъй като браузърът не се свързва със сървъра, когато иска кеширана страница.

    Време за промяна на страницата

    По-практично е да използвате заглавките Last-Modified и If-Modified-Since, налични в HTTP 1.0. Технически известно като правене на условна GET заявка, вие връщате всяко съдържание въз основа на условието на заглавката на заявката If-Modified-Since.

    Когато използвате този метод, трябва да изпращате заглавка Last-Modified всеки път, когато се осъществява достъп до вашия PHP скрипт. Следващия път, когато браузърът поиска страницата, той ще изпрати заглавка If-Modified-Since, съдържаща времето, което вашият скрипт може да използва, за да определи дали страницата е била актуализирана от последно искане. Ако това не е така, вашият скрипт изпраща код на състоянието HTTP 304, за да покаже, че страницата не е променена, без да отпечатва съдържанието на страницата.

    Задайте времето за модификация на кеш файла с този ред: $lastModified = filemtime($cache_file);

    След това, използвайки времето за модификация на кеш файла, изпращаме заглавката Last-Modified. Трябва да изпратим това за всяка обслужвана страница, за да принудим браузъра да ни изпраща заглавка If-Modified-Since с всяка заявка.

    // Излъчване на HTTP заглавката Last-Modified header("Last-Modified: " . gmdate("D, d M Y H:i:s", $lastModified) . " GMT");

    Ако комбинирате подхода на времето последна промянаС времева стойност, която вече е налична във вашето приложение (например времето на най-новата новинарска статия или времето на изтичане от системата за кеширане на сървъра, която видяхме в последното решение), можете да се възползвате от кеша на уеб браузъра и разтоварете връзката за данни чрез възможности за спестяване на информационен трафик от вашия сайт и подобряване на ефективността му.

    Бъдете внимателни, когато тествате каквото и да е кеширане, направено в този стил; ако го направите неправилно, можете да накарате посетителите ви винаги да имат остарели копия на вашия сайт.

    Кеширане на вашите страници в 5 стъпки Оригинал: Публикувано в PHP / JavaScript от ibzi на 17 февруари 2007 г.
    Превод: Кузма Фесков ( [имейл защитен],http://kuzma.russofile.ru)

    Кеширането на вашите страници може да бъде хубав и полезен механизъм, особено ако са генерирани с помощта на PHP и правят много неща SQL заявки. Веднага след като приложите кеширане, вашият сървър веднага ще намали натоварването и ще спре да изяжда много памет за генериране на страници - той просто ще ги зареди от кеша. Ще ви покажа как PHP може да кешира страници и в бъдеще можете да отделите около 5 минути за това.


    Нека да разгледаме технологията за кеширане стъпка по стъпка:

  • В домашната директория създаваме файловете .htaccess, start_cache.php, end_cache.php, както и папка, наречена cache_files.
  • На папката cache_files трябва да бъдат присвоени 777 атрибута.
  • Напишете във файла .htaccess следващите редове: php_value auto_prepend_file /home/username/public_html/start_cache.php php_value auto_append_file /home/username/public_html/end_cache.php низ /начало/потребителско име/public_html/трябва да се замени с пътя към вашата начална директория.
  • Поставяме следния код в скрипта start_cache.php: Не забравяйте да коригирате пътя /начало/потребителско име/public_html/към пътя към началната ви директория.
  • И поставете следния код в скрипта end_cache.php:
  • Всички ваши страници ще бъдат кеширани за 3600 секунди = 1 час. Можете лесно да промените този параметър в скрипта start_cache.php. Кешът на страницата ще бъде записан в папката cache_files.

    Съвсем очевидно е, че в в този случай 777 атрибута са определено нарушение на сигурността. В тази връзка препоръчвам да преместите папката cahce_files извън public_html, например, като я поставите едно ниво по-високо. Това ще блокира достъпа до файловете в него за потребителите на вашия сайт, но няма да повлияе по никакъв начин на работата на системата.

    Освен това този метод има друг сериозен недостатък: авторът на статията поставя целия кеш в една папка, която, ако има достатъчен брой страници на вашия сайт, ще създаде проблем, например на Unix системи има значително забавяне на производителността, когато има повече от 1000 файла в папка. В тази връзка е необходимо да се направят редица промени в алгоритъма и да се организират файловете в отделни подпапки в папката cache_files. Например, като използвате първите 3-4 знака от md5 кеша за това.

    За динамични ресурсиНапълно възможно е да изберете време за кеширане от няколко (5-10) секунди или 1-2 минути, което значително ще намали натоварването на сървъра, но няма да навреди на интерактивността на сайта.

    За страници, за които интерактивността е особено важна, можете да въведете изключения в .htaccess, което ще им позволи постоянно да се променят, а за други страници можете да използвате кеширане.

    Регенериране на съдържание в движение

    Динамично създадени, но статично поддържани страници, т.е. страници, които трябва да бъдат прехвърлени като чисто статични (четени от файлова системаи след това се предават при поискване), но те трябва да бъдат динамично генерирани от уеб сървъра, ако не са във файловата система. По този начин можете да генерирате PHP страници, които се обслужват статично, освен ако някой (или планировчикът) не премахне статичното съдържание. В този случай съдържанието се актуализира.

    Това се прави със следния набор от директиви:

    RewriteCond %(REQUEST_FILENAME) !-s RewriteRule ^page\.html$ page.php

    Тук заявка към page.html кара съответния page.php да се изпълнява вътрешно, ако page.html все още липсва или има нулев размер. Номерът тук е, че page.php е обикновен PHPскрипт, който в допълнение към собствения си изход записва своя изход във файла page.html. Изпълнявайки това веднъж, сървърът предава данните на page.html. Когато уеб администраторът иска да актуализира съдържанието, той просто изтрива page.html (обикновено използвайки cronjob).

    Internet Explorer има проблем с кеширането на страници.

    В IE, когато работите с хедъра "Vary", има една неприятна грешка, свързана с кеширането на страницата. Проблемът се решава чрез добавяне на следните редове към .htaccess:


    кеширане в PHP

    В добрите стари времена, когато създаването на уебсайтове беше толкова просто, колкото въвеждането на няколко HTML страници, изпращането на уеб страници до браузъра беше просто въпрос на изпращане на файл от уеб сървъра. Посетителите на сайта можеха да видят тези малки, само текстови страници почти мигновено (с изключение на потребителите на бавни модеми). След като страницата е заредена, браузърът я кешира някъде на локалния компютър, така че ако страницата бъде поискана отново, той може да извлече локалната версия от кеша, изпращайки само кратка заявка, за да се увери, че страницата на сървъра не е е модифициран. Заявките бяха обработени бързо и най-ефективно и всички бяха доволни (с изключение на тези, които използват 9600 бода модеми).

    Появата на динамични уеб страници промени нещата към по-лошо, ефективно нарушавайки този модел на обслужване на уеб страници поради два проблема:

    1. Когато сървърът получи заявка за динамична уеб страница, се извършва междинна обработка, например парсване на скрипта от PHP двигателя, което трябва да бъде завършено. Това ни дава забавяне, преди уеб сървърът да започне да изпраща изход към браузъра. За прост PHP скрипт това не е от голямо значение, но в случай на по-сложно приложение, PHP двигателят може да извърши много действия, преди страницата да е готова за изпращане. Тези допълнителни стъпки водят до забележимо забавяне между потребителските заявки и страниците, които действително се показват в техните браузъри.

    2. Типичен уеб сървър, като Apache, използва времето за модификация на файла, за да информира правилно браузъра за състоянието на кеша на исканата страница. В динамичните уеб сайтове самият PHP скрипт може да се променя само от време на време, докато съдържанието, което показва, вероятно намиращо се в база данни, се променя често. Уеб сървърът няма начин да разбере за промени в базата данни, така че не изпраща последната дата на модификация. Ако клиентът (браузърът) не получи никаква индикация за това колко време данните са правилни, той приема, че трябва да поиска нова страница следващия път. Уеб сървърът винаги ще отговаря актуализирана версиястраници, независимо дали данните са променени. За да избегнат този недостатък, повечето уеб разработчици използват мета тагове или HTTP заглавки, за да инструктират браузъра никога да не използва кешираната версия на страницата. Това обаче отрича естествената способност на уеб браузъра да кешира уеб страници и има някои значителни недостатъци. Например, съдържанието на динамична страница може да се променя веднъж на ден, така че ползата от това, че браузърът кешира страницата дори за 24 часа, е очевидна.

    Обикновено за малки PHP приложения е напълно възможно да пренебрегнете съществуването на тези проблеми, но с нарастването на сложността и трафика на вашия сайт може да се натъкнете на проблеми. Въпреки това и двата проблема могат да бъдат решени: първият чрез кеширане от страна на сървъра, вторият чрез управление на кеширането от страна на клиента от вашето приложение. Подходът, който ще предприемете, ще зависи от вашите специфични нужди, но в тази статия ще ви покажем как можете да разрешите и двата проблема, като използвате PHP и някои класове на библиотека PEAR.

    как да попреча на браузърите да кешират страница?

    Преди да разгледаме техниките за кеширане на клиенти и сървъри, първо трябва да разберем как да попречим на уеб браузъра (и прокси сървърите) да кешира страници на първо място. Основният начин за постигане на това е използването на HTML мета тагове:

    Като вмъкнете минала дата в мета тага Expires, казвате на браузъра, че кешираното копие на страницата винаги е остаряло. Това означава, че браузърът никога не трябва да кешира страницата. Мета таг Pragma: no-cache е доста добре поддържана конвенция, която повечето уеб браузъри следват. След като открият този маркер, те обикновено не кешират страницата (въпреки че няма гаранция, това е просто конвенция). Това звучи добре, но има два проблема с използването на мета тагове:

    1. Ако маркерът не е съществувал, когато страницата е била поискана за първи път от браузъра, но се появява по-късно (например сте модифицирали файла за включване на pageheader.php, който е заглавката на всяка уеб страница), браузърът ще остане в блажено неведение и използва неговото кеширано копие на оригинала.

    2. Прокси сървърите, които кешират уеб страници, изобщо няма да проверяват директно съдържанието на HTML документа. Вместо това те разчитат само на уеб сървъра, от който идват документите, и HTTP протокол. С други думи, браузърът може да мисли, че не трябва да кешира страницата, но проксито между браузъра и уеб сървъра вероятно не знае това - и ще продължи да изпраща същата страница на клиента.

    По-добър подход е да използвате HTTP протокола директно с помощта на функцията за заглавка на PHP:


    заглавие ("Pragma: без кеш");
    ?>

    Можем да отидем една крачка напред, като използваме заглавката Cache-Control, която е съвместима с браузъри, които поддържат HTTP 1.1:

    заглавие ("Изтича: понеделник, 26 юли 1997 г. 05:00:00 GMT");
    header("Cache-Control: no-store, no-cache, must-revalidate");
    header("Cache-Control: post-check=0, pre-check=0", FALSE);
    заглавие ("Pragma: без кеш");
    ?>

    Това гарантира, че нито един уеб браузър или междинен прокси сървър не кешира страницата, така че посетителите винаги получават най-актуалната версия на съдържанието. Всъщност първата заглавка трябва да е самостоятелна; това е най-добрият начин да се гарантира, че страницата не е кеширана. Заглавките Cache-Control и Pragma се добавят за целите на безопасността. Въпреки че не работят във всички браузъри или проксита, те ще уловят някои случаи, в които Expires не работи според очакванията (например, ако датата на компютъра на клиента е зададена неправилно). Разбира се, пълното избягване на кеширането ни поставя пред проблемите, които обсъдихме в началото на тази глава. Сега ще разгледаме решаването на тези проблеми.

    Internet Explorer и кеширане на файлове за изтегляне

    Проблеми могат да възникнат, когато се занимавате с кеширане и изтегляне на файлове. Ако при обслужване на изтегляне на файл от PHP скрипт се използват заглавки като Content-Disposition: attachment, filename=myFile.pdf или Content-Disposition: inline, filename=myFile.pdf, ще имате проблеми с Internet Explorer, ако кажете на браузъра да не кешира страницата.

    Internet Explorer обработва изтеглянията по доста необичаен начин, като прави две заявки към уебсайта. Първата заявка изтегля файла и го съхранява в кеша, докато не бъде направена втората заявка (без да съхранява отговора). Тази заявка задейства процеса на прехвърляне на файла до крайния потребител според типа на файла (например стартира Acrobat Reader, ако файлът е PDF документ). Това означава, че ако изпратите заглавки, които пречат на браузъра да кешира страницата, Internet Explorer ще изтрие файла между първата и втората заявка, което ще доведе до нищо за крайния потребител. Ако файлът, който обслужвате като PHP скрипт, не се променя, едно от най-простите решения е да премахнете заглавките за „кеширане“ от скрипта.

    Ако изтегляният файл се променя редовно (т.е. искате браузърът да изтегли най-новата версия), трябва да използвате заглавката Last-Modified и да се уверите, че времето за модификация между две последователни заявки не се променя. Трябва да направите това по начин, който не засяга потребителите на браузъри, които обработват правилно изтеглянията. Едно решение в този случай би било да съхраните файла на вашия уеб сървър и да предоставите проста връзка към него, позволявайки на уеб сървъра да докладва кеширащите заглавки вместо вас. Разбира се, това решение може да не е приемливо, ако се предполага оторизиран достъп до файла, тъй като позволява директно зареждане на съхранения файл.

    как мога да заснема данни от страната на сървъра за кеширане?

    Време е да разгледаме как можем да намалим забавянето с помощта на кеширане на изход от страна на сървъра. Така че можете да обслужвате страницата както обикновено, изпълнявайки заявки към база данни и така нататък в PHP. Но преди да изпратим резултата до браузъра, ние го улавяме и запазваме готовата страница, например във файл. При следващата заявка PHP скриптът първо проверява за кеширана версия на страницата. Ако съществува, скриптът изпраща кешираната версия на браузъра, като по този начин елиминира забавянето при повторното създаване на страницата.

    Няколко думи за кеширането с помощта на шаблони. Наличието на шаблонни машини като Smarty често говори за кеширане на шаблони. Обикновено тези машини предлагат вграден механизъм за запазване на компилираната версия на шаблона (т.е. генериране на PHP източник от шаблона), което ни предпазва от необходимостта да анализираме шаблона всеки път, когато бъде заявена страница. Това не трябва да се бърка с изходното кеширане, което се отнася до кеширане на предоставения HTML (или друг изход), който PHP изпраща на браузъра. Можете успешно да използвате и двата вида кеширане едновременно на един и същи сайт.

    Сега ще разгледаме вградения в PHP механизъм за кеширане, който използва изходно буфериране, което можете да използвате независимо от това как създавате вашето съдържание (със или без шаблони). Помислете за ситуация, в която вашият скрипт показва резултата, използвайки например echo или print за извеждане на данни директно в браузъра. В този случай можете да използвате контролните функции PHP изходза съхраняване на данни в буферна памет, над които вашият PHP скрипт има контрол.
    Ето един прост пример:


    ob_start();
    // Изведе малко текст (който се записва в буфера);
    echo "1. Изведете това в буфера
    ";
    // Получаване на съдържанието на буфера
    $buffer = ob_get_contents();
    // Спрете буферирането и изчистете изходния буфер
    ob_end_clean();
    // Извежда малко текст както обикновено
    ехо "2. Нормален изход
    ";
    // Отпечатване на съдържанието на буфера
    ехо $ буфер;
    ?>

    Самият буфер съхранява изхода като низ. И така, в горния скрипт започваме буферирането с ob_start и използваме ехо, за да изведем нещо. След това използваме ob_get_contents, за да извлечем данните, буферирани от оператора echo, и да ги съхраним в низ. Функцията ob_end_clean спира изходното буфериране и унищожава съдържанието му. Като алтернатива можете да използвате ob_end_flush за отпечатване на съдържанието на буфера. Горният скрипт ще изведе:

    2. Нормален изход
    1. Изведете това в буфера

    С други думи, ние уловихме резултата от първото ехо, след което го изпратихме на браузъра след второто ехо. Както се вижда от това прост пример, изходното буфериране е много мощен инструментза да формулирате вашия сайт, той предоставя решение за кеширане, както ще видим скоро, и е чудесен начин да скриете грешки от посетителите на вашия сайт. Освен това осигурява алтернативна възможностза пренасочване на браузъра в ситуации като удостоверяване на потребителя.

    HTTP заглавки и изходно буфериране

    Изходното буфериране може да помогне за решаването най-много често срещан проблемсвързани с функцията за заглавка, да не говорим за session_start и set_cookie. Обикновено, ако извикате някоя от тези функции, след като страницата е започнала да се изобразява, ще получите неприятно съобщение за грешка. Когато буферирането на изхода е активирано, единственият тип изход, който избягва буферирането, са HTTP заглавките. Като използвате ob_start в самото начало на изпълнението на вашето приложение, можете да изпращате заглавки във всяка точка на програмата, която желаете, без да срещате обичайните грешки. След това, след като сте сигурни, че не е необходимо да отпечатвате повече HTTP заглавки, можете веднага да отпечатате съдържанието на страницата от буфера.

    /* Трябва да се отбележи, че такова използване на тази функция е неоправдано. В повечето случаи просто няма нужда да се използва изходно буфериране, за да се отървете от грешки от този тип и всичко може лесно да бъде коригирано чрез подходящ дизайн на приложението - приблизително. преводач */

    използване на изходно буфериране за кеширане от страна на сървъра

    Вече видяхте основен пример за буфериране на изхода, сега следващата стъпка е мястото, където буферът се записва във файл:

    // Ако съществува кеширана версия...
    if (file_exists("./cache/2.cache")) (
    // Прочетете и изведете файла
    readfile("./cache/2.cache");
    изход();
    }
    // Стартиране на буфериране на изхода
    ob_start();
    // Изведете останалата част от HTML
    ?>
    >http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    >http://www.w3.org/1999/xhtml">

    Кеширана страница

    Тази страница е кеширана с помощта на PHP
    Функции>http://www.php.net/outcontrol">Функции за контрол на изхода

    // Получаване на съдържанието на буфера
    $buffer = ob_get_contents();
    // Спрете буферирането и изведете буфера
    ob_end_flush();
    // Запазване на кеш файл със съдържание
    $fp = fopen("./cache/2.cache", "w");
    fwrite($fp, $buffer);
    fclose($fp);
    ?>

    Първо, този скрипт проверява за наличието на версия на страницата в кеша и ако съществува, скриптът я чете и показва. В противен случай той използва изходно буфериране, за да създаде кеширана версия на страницата. След използване на ob_end_flush за показване на страницата на потребителя, тя се записва като файл.

    блоково буфериране

    При опростен подход ние кешираме изходния буфер като една страница. Този подход обаче лишава реални възможности, осигурен от функциите за контрол на изхода на PHP.
    Без съмнение, някои части от страницата, които изпращате на вашия посетител, се променят много рядко, като заглавката, менюто и долния колонтитул. Въпреки това, други части, като например таблици, съдържащи форумни дискусии, може да се променят доста често. Изходното буфериране може да се използва за кеширане на секции от страница отделни файлове, след това създайте страница от тях - решение, което елиминира необходимостта от повтарящи се заявки към базата данни, докато циклии т.н. Можете да зададете на всеки блок на страница дата на изтичане, след която кеш файлът се създава отново, или като алтернатива можете да включите механизъм във вашето приложение, който ще изтрива кеш файла всеки път, когато съдържанието, съхранено в него, бъде променено.
    Ето пример, демонстриращ този принцип:

    /
    * Запишете кеш файл
    * @param съдържание на низ – съдържание на буфер
    * @param string име на файл – име на файл, използвано при създаване на кеш файла
    * @return void
    */
    функция writeCache($съдържание, $име на файл) (
    $fp = fopen("./cache/" . $filename, "w");
    fwrite($fp, $content);
    fclose($fp);
    }
    * Проверка на кеш файлове
    * @param string filename – име на кеш файла за проверка
    * @param int expiry – максимална „възраст“ на файла в секунди
    * @return смесено съдържание на кеша или невярно
    */
    функция readCache($filename, $expiry) (
    if (file_exists("./cache/" . $filename)) (
    if ((time() - $expiry) >filemtime("./cache/" . $filename))
    върне FALSE;
    $cache = file("./cache/" . $filename);
    return implode("", $cache);
    }
    върне FALSE;
    }
    ?>

    Първите две функции, които дефинирахме - writeCache и readCache - се използват съответно за създаване на кеш файлове и проверка на тяхното съществуване. Функцията writeCache приема като аргументи данните, които трябва да бъдат кеширани, и името на файла, използвано за създаване на кеш файла. Функцията readCache получава името на кеш файла и времето в секунди, след което кеш файлът трябва да се счита за остарял. Ако намери кеш файла за валиден, скриптът ще върне съдържанието му, в противен случай ще върне FALSE, за да покаже, че кеш файлът не съществува или е остарял.

    В този пример използвах процедурен подход. Въпреки това не препоръчвам да правите това на практика, тъй като ще се окаже много объркан код (вижте следващите решения за по-добра алтернатива) и вероятно ще причини проблеми със заключването на файлове (например какво се случва, когато някой получи достъп до кеша, докато е се актуализира?)
    Нека продължим с този пример. След като изходното буфериране започне, започва обработката. Скриптът първо извиква readCache, за да види дали файлът 3_header.cache съществува - той съдържа заглавката на страницата, тоест HTML заглавката и началото на тялото. Ние използваме функцията за дата, за да изведем часа, в който страницата е действително генерирана, така че ще видите различните кеш файлове в действие, когато страницата бъде изобразена.

    // Стартиране на буфериране на изхода
    ob_start();
    // Обработка на заглавката
    if (!$header = readCache("3_header.cache", 604800)) (
    // Извеждане на заглавката
    ?>
    >http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    >http://www.w3.org/1999/xhtml">

    Страницата се кешира блок по блок

    Време за създаване на заглавката:

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

    Какво се случва, когато кеш файлът не бъде намерен? Част от съдържанието се извежда и се присвоява на променлива с помощта на ob_get_contents, след което буферът се изчиства от функцията ob_clean. Това ни позволява да улавяме изхода част по част и да го съпоставяме с отделни кеш файлове с помощта на writeCache. Заглавието на страницата вече се съхранява като файл, който може да се използва без нашата намеса при повторното изграждане на страницата. Нека се върнем в началото за секунда. условен оператор. Когато извикахме readCache, ние му предадохме живот на кеша от 604800 секунди (една седмица), readCache използва времето за модификация на кеш файла, за да определи дали кеш файлът все още е валиден.

    За съдържанието (тялото) на страницата ще продължим да използваме същия процес. Въпреки това, този път, когато извикаме readCache, ще използваме живот на кеша от пет секунди, кеш файлът ще бъде модифициран всеки път, когато е „по-стар“ от 5 секунди:

    // Обработка на тялото на страницата
    if (!$body = readCache("3_body.cache", 5)) (
    echo "Време за създаване на тялото: ". дата ("H:i:s") . "
    ";
    $body = ob_get_contents();
    ob_clean();
    writeCache($body, "3_body.cache");
    }
    ?>

    Долният колонтитул може ефективно да се променя по същия начин като горния колонтитул.
    Крайният резултат изглежда по следния начин:
    - време за създаване на хедър - 17:10:42;
    - време за създаване на тялото - 18:07:40;
    - време на създаване на колонтитул - 17:10:42.
    Горният и долният колонтитул се актуализират всяка седмица, докато тялото се променя, когато е по-старо от 5 секунди.

    вложени буфери

    Можете да влагате един буфер в друг практически за неопределено време просто като извиквате ob_start многократно. Това може да бъде полезно, ако имате много операции, които използват изходния буфер, например някои, които улавят PHP съобщения за грешки, други, които се занимават с кеширане. Трябва да се уверите, че ob_end_flush или ob_end_clean се извикват всеки път, когато се използва ob_start.

    Как мога да внедря проста система за кеширане от страна на сървъра?
    Сега, след като разбираме идеите зад буферирането на изхода, е време да разгледаме как можем да приведем този процес в действие по начин, който е лесен за поддръжка. За да направим това, ще използваме малко помощ от PEAR::CacheLite.

    Както казах, в интерес на улесняването на поддържането на вашия код и наличието на надежден механизъм за кеширане, е разумно да възложите отговорността за логиката на кеша на класове, на които имате доверие. Cache_Lite е мощна, но лесна за използване библиотека за кеширане, която се грижи за задачи като временно заключване на кеш файлове, тяхното създаване и валидиране, управление на изходния буфер и директно кеширане на резултата от функция или клас метод. Основната причина за избора на тази библиотека е сравнително простата интеграция на Cache_Lite във вече съществуващо приложение, което изисква само малки промени в кода.

    Cache_Lite се състои от три основни класа. Първият е базовият клас Cache_Lite, който отговаря само за създаването и четенето на кеш файлове и не буферира изхода. Този клас може да се използва самостоятелно в случаите, когато не е необходимо да се използва буфериране на изхода, като например при запазване на резултата от анализиране на шаблон от PHP скрипт. Показаните тук примери не използват директно класа Cache_Lite и демонстрират използването на другите два класа. Cache_Lite_Function се използва за извикване на функция или метод на клас и след това кеширане на резултатите. Това може да бъде полезно, например, за кеширане на резултата от MySQL заявка. Класът Cache_Lite_Output използва функциите за контрол на изхода на PHP, за да прихваща данни, генерирани от скрипт, и да ги съхранява в кеш файлове. Това ви позволява да изпълнявате същите задачи като предишното решение.

    Настройки на Cache_Lite

    IN текуща версияклас (1.1) са налични следните настройки:
    - cacheDir - директория, където ще бъдат поставени кеш файловете. Стойността по подразбиране е директорията, в която се изпълнява скриптът;
    - кеширане - тази опция активира или деактивира възможностите на Cache_Lite. Например, ако имате много заявки към Cache_Lite и по време на отстраняване на грешки искате да изключите кеширането, задайте го на FALSE. Стойността по подразбиране е TRUE.
    живот - параметърът съдържа продължителността на живота на кеша по подразбиране (в секунди);
    - FileNameProtection - използвайте MD5 кодиране за генериране на име на кеш файл. Това ви позволява да използвате всякакви символи в имената на кеш файловете и групите, дори тези, които са забранени от файловата система;
    - fileLocking - активира механизми за блокиране на файл с кеш, докато се записват данни в него;
    - writeControl - проверява дали кеш файлът е записан правилно веднага след края на записа;
    - readControl - преди да прочете кеш файл, го проверява за изкривявания;
    - readControlType - този параметър определя типа на механизма за четене на кеш файлове. Налични механизми: циклична проверка на излишъка, MD5 хеш или проста проверкадълго Имайте предвид, че този механизъм не е предназначен да предпазва кеш файловете от директно извикване външни потребители. Това е просто начин да се определи дали даден файл е повреден или не;
    - pearErrorMode - активира метода PEAR за връщане на грешки;
    - memoryCaching - всеки път, когато извикате кеша за запис във файл, той се записва в масива Cache_Lite. saveMemoryCachingState и
    getMemoryCachingState се използват за достъп до кеша, съхранен в паметта между заявките. Предимството на този метод е, че съдържанието на кеша може да се съхранява в един файл, което намалява броя на циклите за четене/запис на диска. Кешът се възстановява директно в масив, до който вашият скрипт има достъп;
    memoryCachingLimit - параметърът определя ограничението за броя на кеш файловете, които могат да се съхраняват в масив в паметта.

    изчистване на кеша

    Cahce_Lite съдържа успешен механизъм за определяне на живота на кеш файловете, който създава добра основаза безопасността на вашите файлове и навременното им актуализиране. Въпреки това, има моменти, когато трябва незабавно да актуализирате вашия кеш файл. За такива случаи има методи remove() и clean(). Методът remove() е предназначен за премахване на конкретен кеш файл. изисква ИД на кеша и името на групата, към която принадлежи файлът. Следният пример ще изтрие основния кеш файл от предишния пример:

    $cache->remove("body", "Dynamic");

    Методът clean() ни позволява да изтрием всички файлове в нашата директория, ако го извикаме без параметри. Ако подадете името на групата като параметър, всички файлове, включени в тази група. Ако искахме да премахнем заглавката и долна част, тогава трябва да издадете команди, подобни на тази:

    $cache->clean("Static");

    Методите remove() и clean() очевидно трябва да бъдат извикани в отговор на събития в приложението. Например, ако имате форум, вероятно трябва да изтриете кеш файла, ако някой потребител публикува ново съобщение. Въпреки че това решение изглежда добре, то може да включва някои промени в кода. Ако имате основен сценарий, който се свързва с всяка страница от приложението, която посетител може да види, можете просто да следите за входящи събития, като променливата $_GET["newPost"], премахвайки необходимите кеш файлове. Това ще ви позволи да създадете централизиран механизъм за управление на кеша. Можете дори да включите този код в php.ini.

    извиквания на кеширащи функции

    Тъй като уеб услугите са достъпни през мрежата, често е добра идея да кеширате резултата, така че да може да се изпълни локално, вместо да изпълнявате една и съща бавна заявка многократно. В най-простия случай бихме могли да използваме PHP сесии, но тъй като това решение работи въз основа на редовността на посетителите, отварянето на заявка за всеки посетител все още ще бъде бавно. В такива случаи Cache_Lite може да бъде много полезен.

    Уеб инсталаторът на PEAR използва Cache_Lite за кеширане на XML-RPC заявки, изпратени до уеб сървъра на PEAR.
    Ето кода, който получава данни от отдалечения сървър:

    $countries = $stationInfo->listCountries();

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

    И в двата случая тези повиквания съответстват на заявка за данни по мрежата. Използвайки Cache_Lite, бихме могли да кешираме данните, върнати от услугата, и да можем да ги използваме повторно. Това ще избегне допълнителни ненужни мрежови връзкии значително ще увеличи скоростта на изпълнение. Моля, имайте предвид, че тук разглеждаме само код, свързан с нашата тема. Първо активираме Cache_Lite_Function:

    // Включете PEAR::Cache_Lite_Function
    require_once "Кеш/Lite/Function.php";

    // Задайте параметри за за Cache_Lite_Function
    // ПРЕДУПРЕЖДЕНИЕ: fileNameProtection = TRUE!
    $опции = масив(
    "cacheDir" =>"./cache/",
    "fileNameProtection" =>ВЯРНО,
    "writeControl" => ВЯРНО,
    "readControl" =>ВЯРНО,
    "readControlType" => "strlen",
    "defaultGroup" =>"SOAP"
    );
    // Създаване на обект от класа Cache_Lite_Function
    $cache = нова Cache_Lite_Function($options);

    Важно е параметърът fileNameProtection да е зададен на TRUE. Тази стойност е по подразбиране, но аз специално я зададох ръчно, за да подчертая нейното значение. Ако зададете този параметър на FALSE, получавате невалидно имефайл, така че няма да има кеширане.
    След това отправяме заявка към нашия SOAP клиент:

    $countries = $cache->call("stationInfo->listCountries");
    $country = $cache->call("stationInfo->searchByCountry",
    $_GET["държава"]);

    Ако заявка е направена за първи път, Cache_Lite_Function съхранява резултатите като сериализиран масив в кеш файл (не е нужно да се притеснявате за това) и този файл ще се използва за бъдещи заявки, докато не изтече живота му. setLifeTime може да се използва, за да се определи колко дълго ще живее кеш файл, преди да се актуализира информацията му. Стойността по подразбиране е 1 час (3600 секунди).

    PEAR::Кеш

    Като цяло Cach_Lite предоставя единна, лесна за използване система за решаване на всякакви проблеми, свързани с кеширането. защото следващо ниво- това са сайтове с особено голям трафик, трябва да се справите с PEAR::Cache - "големият брат" на Cache_Lite. Той също така предоставя подобрени възможности за кеширане, като например кеширане в споделена памет като алтернатива на кеширането на файлове, или Msession PHP разширението помага чрез съхраняване на данни в балансирана сесия, което е особено полезно в балансирани уеб сървъри. Cache_Lite обаче предлага повече от достатъчно функции и отговаря на нуждите на повечето сайтове.

    как да управлявате кеширане от страна на клиента с помощта на PHP?

    Сега, след като разгледахме опциите за отмяна на кеширането от страна на клиента, време е да разгледаме механизъм, който ще ни позволи да контролираме кеша от страна на клиента с помощта на PHP. Този подход ще работи само ако използвате PHP заедно с Apache сървъртъй като ще използваме функцията getallheaders, за да получим заглавките, изпратени от браузъра. Тази функция работи само в Apache. Ако използвате PHP 4.3.0 с Apache, работата с HTTP заглавки е възможна чрез функциите apache_request_headers и apache_response_headers. Функцията getallheaders се превърна в псевдоним на новата функция apache_request_headers.

    Механизмът за работа с кеша на уеб браузъра отново е HTTP. Множество заглавки участват в инструктирането на уеб браузърите и прокси сървърите да кешират независимо една страница. Ситуацията се усложнява от факта, че някои от тях са достъпни само с HTTP 1.1.

    проверка на HTTP заглавките във вашия браузър

    Прост, но много удобен инструмент за проверка на заглавките на заявките и отговорите е LiveHttpHeaders - добавка за Браузър Mozilla. Важно е да знаете какви точно заглавки изпраща вашият скрипт, особено когато имате работа с HTTP кеширащи заглавки.
    За простота ще разгледаме само заглавките за кеширане на HTTP 1.0, а именно Expires, Last-Modified и If-Modified-Since, както и HTTP 304 (непроменен) код на състоянието.

    Други заглавки, налични с HTTP 1.1, като Cache-Control и ETag, са предназначени да осигурят разширен механизъм, който може да се използва във връзка със състоянието на уеб сесията, с други думи, версията на същата страница, предназначена за неоторизиран посетител, може да се различава значително от показано на оторизирания потребител. HTTP 1.1 заглавки първоначално бяха добавени, за да позволят такива страници да бъдат кеширани.

    изтичане на жизнения цикъл на страницата

    Най-лесният за използване заглавка е заглавката Expire, която задава датата, на която страницата ще изтече. До този момент на уеб браузъра е разрешено да използва кеширана версия на страницата.
    Пример:


    функция setExpires($expires)(
    header("Изтича: " . gmdate("D, d M Y H:i:s", време() + $изтича) . "GMT");
    }
    echo „Тази страница ще се самоунищожи след 10 секунди
    ";
    ехо "Сега". gmdate("H:i:s") . " GMT
    ";
    ехо "
    ";
    ?>

    Горният пример показва текущото GMT време и показва връзка, която ви позволява да се върнете към страницата. С помощта на бутона Refresh на вашия браузър можете да кажете на браузъра, че искате да обнови кеша.

    дати и часове в HTTP

    Датите в HTTP винаги се изчисляват спрямо средното време по Гринуич (GMT). PHP функцията gmdate е точно същата функция като date, с изключение на това, че автоматично компенсира GMT въз основа на системния часовник и регионалните настройки на вашия сървър. Когато браузърът срещне заглавката Expires, той кешира страницата. Всички последващи заявки за страницата, направени преди определеното TTL време, използват кешираната версия на страницата, без да правят заявки към уеб сървъра.
    Заглавката Expires е лесна за прилагане по принцип, но в повечето случаи, освен ако не сте високо организиран човек, не можете да знаете точно кога дадена страница на вашия сайт ще бъде актуализирана. защото браузърът ще влезеза да се свържете със сървъра само след като страницата е остаряла, няма начин да кажете на браузъра, че страницата в неговия кеш е остаряла.

    време за промяна на страницата

    По-практично е да използвате заглавките Last-Modified и If-Modified-Since, налични в HTTP 1.0. Когато използвате този метод, трябва да изпратите заглавка Last-Modified в отговор на всяка заявка към вашия PHP скрипт. Следващият път, когато браузърът поиска страницата, той ще изпрати заглавка If-Modified-Since, съдържаща времето, което вашият скрипт може да използва, за да определи дали страницата е била актуализирана след последната заявка. Ако това не е така, вашият скрипт изпраща код на състоянието HTTP 304, за да покаже, че страницата не е променена, без да отпечатва съдържанието на страницата. Ако комбинирате подхода за последно променено време с времева стойност, която вече е налична във вашето приложение (например часа на най-новата новинарска статия), можете да се възползвате от кеша на уеб браузъра и да разтоварите връзката за данни, запазвайки информация трафик от вашия сайт, където е възможно, подобряване на ефективността му.

    Бъдете внимателни, когато тествате каквото и да е кеширане, направено в този стил: ако го направите неправилно, можете да накарате посетителите ви винаги да имат остарели копия на вашия сайт.

    Хари Фюкс, превод на Сергей Мълин (SiMM) и Кузма Фесков.

    Когато разработвате PHP проекти от нулата и без да използвате библиотеки, скоростта може да се превърне в сериозен проблем. Кеширането може значително да повлияе на скоростта на уеб страниците. В този урок ще ви покажем проста и ефективен начиндинамично кеширане на страници, които се нуждаят от ускорение.

    Първа стъпка. Създайте файл top-cache.php

    Трябва да създадем два файла. Първо: създайте файл с име top-cache.php и копирайте следния код в него:

    Какво се случва в този код? Първите 5 реда създават името на кеш файла според текущ PHPфайл. Например, ако използваме файл с име list.php, кешираният файл ще изглежда като cached-list.html.

    Ред 6 създава променливата $cachetime, която указва живота на кеша.

    Редове от 9 до 13 дефинират условен израз, който проверява съществуването на файл с името, дефинирано в променливата $cachefile. Ако файлът съществува, се вмъква коментар заедно с файла, дефиниран в променливата $cachefile. След това операторът за изход прекъсва скрипта и файлът се изпраща до браузъра на клиента. Тоест, ако бъде намерен статичен файл, PHP кодът няма да бъде изпълнен от сървъра.

    Ред 14 създава буфер, ако файлът, зададен от $cachefile, не бъде намерен.

    Стъпка втора. Създайте файл bottom-cache.php

    Сега нека създадем втория PHP файлс името bottom-cache.php и копирайте следния код в него:

    Ако файл с името, дефинирано в променливата $cachefile, не съществува на сървъра, този код се изпълнява и файлът се създава. Следващият път, когато се отвори страницата, статичният $cachefile ще обслужва браузъра на клиента, вместо да изпълни целия код на PHP скрипта.

    Стъпка трета. Включване на кеш файлове в кода на страницата

    Сега имаме две необходим файл. Просто ги включваме PHP страница, който трябва да бъде кеширан. Файлът top-cache.php трябва да бъде включен в горната част на страницата, а файлът bottom-cache.php в края:

    Сега, ако проверите кеширането на бавни страници, тогава можете да видите колко по-бързо се зареждат.

    Съвременните браузъри доста често използват локален кеш в работата си. какво значи това Това означава, че браузърът, след като получи HTML документ, картина или друг ресурс от сървъра, го поставя в своя локален кеш (с други думи, записва получения ресурс в твърд дискпотребителска машина) и по време на последващи заявки към такъв ресурс няма достъп до сървъра, а получава ресурса от локалния кеш.

    Този алгоритъм на браузъра драстично увеличава скоростта на зареждане на HTML документи. Тъй като, ако ресурсът вече е зареден и в резултат се намира в локалния кеш, тогава времето за достъп се определя не от честотната лента на комуникационния канал (например модемна връзка), а от скоростта на твърдия диск .

    Въпреки това, заедно с предимствата този методсъщо поражда редица проблеми. По-специално, повечето начинаещи уеб програмисти, когато разработват динамични сайтове, се сблъскват със същия проблем. Същността на този проблем е, че вместо многократно да се свързва със сървъра за страница, която изпълнява скрипт на сървъра, който променя някаква информация, браузърът осъществява достъп до локалния кеш. И в резултат на например три заявки няма три модификации на информацията, намираща се на сървъра, а само една.

    За да принудите браузъра да изисква страница от сървъра всеки път, трябва да забраните на браузъра да влиза този ресурсда кеширате. По-долу са най-често срещаните методи за деактивиране или заобикаляне на кеширането.

    Генериране на нов URL

    Да приемем, че исканият ресурс има следния url: test.html?id=7. Както можете да видите от URL адреса, към него се предава един параметър. Да добавим например кога Помощ за JavaScript, има още един параметър в URL адреса и ние ще го направим неговата стойност произволно число. В резултат URL адресът ще изглежда така: test.html?id=7&rnd=0.6700820127538827. Случайният параметър ще се генерира отново всеки път. По-долу е даден списък, демонстриращ този подход:

    Генериране на нов URL адрес document.write("");

    тестова връзка
    Всеки път, когато резултатът от такава заявка ще бъде кеширан, но тъй като кеширането се извършва върху целия url, всеки път ще се получава нов url и браузърът ще бъде принуден да поиска ресурс от сървъра, тъй като url адресите на две заявки няма да съвпадат точно.

    Заглавни полета

    Можете също така да управлявате кеширането от страната на сървъра. За да се постигне това, ресурсът, изпратен до браузъра, е придружен от полета за заглавка. Подробно описание на заглавните полета може да се намери в стандарта Rfc 2068, който описва протокола HTTP 1.1.

    Полето за заглавка изтича

    Стойността на този хедър е датата, след която съдържанието на ресурса ще стане неактуално. Ако потребител получи достъп до ресурс след тази дата, браузърът трябва да поиска ресурса от сървъра, а не от локалния кеш.< содержит дату, прошедшую, по отношению к текущей, то при следующем обращении к ресурсу браузер будет вынужден снова обратиться к серверу. Это произойдет вследствие того, что либо документ не будет занесен в кэш — как уже устаревший, либо при обращении к кэшу браузер определит, что документ уже устарел. Следующий листинг на PHP демонстрирует использование заголовка Expires:

    Ако полето >Изтича

    Последно модифицирано заглавно поле Стойността на тази заглавка е датата, на която ресурсът е последно актуализиран. мнозинствомодерни браузъри

    използвайте следния алгоритъм, ако ресурсът вече е в локалния кеш:
    * изисква от сървъра датата на последната актуализация на ресурса
    * сравнява получената дата и датата на ресурса в локалния кеш

    * ако ресурсът на сървъра е по-нов от ресурса в кеша, ресурсът се изисква от сървъра Ако ресурс, разположен на сървъра, съдържа в това полетекуща дата

    , тогава браузърът ще изисква ресурса от сървъра всеки път, а не от локалния кеш. Следният списък демонстрира използването на заглавното поле Last-Modified:

    header("Последна промяна: " . gmdate("D, d M Y H:i:s") . " GMT"); ПолетаЗаглавка Cache-Control

    и Pragma

    И накрая, заглавните полета, които са пряко отговорни за кеширането на ресурсите. Полето е дефинирано в стандарта RFC 1945, описващ протокола HTTP 1.0. Това поле се счита за остаряло, но в някои случаи е необходимо да се използва. По-специално, някои прокси сървъри не обработват правилно заявките за постоянно променящи се ресурси, ако това поле на заглавката не е изпратено заедно с ресурса.

    header("Cache-Control: no-cache, must-revalidate"); заглавие ("Pragma: без кеш");

    Добър Лош