Pluginów do cache’owania stron stworzonych w WordPress jest wiele. I całe szczęście, bo niestety są sytuacje, w których WordPress ma spore problemy z prędkością. Niestety jak do tej pory nie udało mi się znaleźć rozwiązania idealnego. Dlatego też chcę przedstawić własne rozwiązanie, pomagające przyspieszyć generowanie stron unikając zbytniego mielenia funkcjami php i odpytywania bazy danych.
Podstawowym problemem wszystkich pluginów jest fakt, że cache’owania jest fakt, że strony są przechowywane w całości. Plugin raz na jakiś czas generuje całe strony i dopiero po określonym odstępie czasu generowanie się powtarza. To sprawia sporo problemów z choćby obsługą ciasteczek: nie można rozpoznawać użytkownika po ciasteczku i wysyłać mu spersonalizowanej strony, bo WordPress z takim pluginem do wszystkich wysyła takie same strony.
Oczywiście są metody na obejście tego, jednak każda ma jakieś wady. Można w ustawieniach pluginu zarządać aby nie cache’ował poszczególnych stron, nie działał gdy użytkownik jest zalogowany, można też w WP Super Cache użyć odpowiednich hacków. Jednak zawsze oznacza to całkowite wyłączenie cache’owania. Cała strona jest cache’owana lub niecache’owana.
A co jeśli by podejść do zagadnienia pregenerowania zawartości nieco inaczej? Czy na pewno musimy pregenerować całe strony od <html> do </html> ?
Odpowiedź brzmi: oczywiście nie. Skoro szablony i tak mamy rozbite na najczęściej 5 plików – header.php, index.php, sidebar.php, footer.php i style.css, index.php włącza w siebie pozostałe pliki wcześniej je generując (za wyjątkiem oczywiście pliku stylów, ten jest statyczny), czy na pewno na przykład header.php musi być generowany za każdym razem? Nawet jeśli musi (bo na przykład ma odwołania do plików JS zależnych od zawartości konkretnej strony): czy każdy fragment takiego pliku musi być generowany za każdym razem? Jestem niemal pewien, że obecny w chyba każdym pliku nagłówka kod bloginfo(‘charset’) generuje zawsze to samo od powstania blogu, aż do jego “śmierci”.
Można też znaleźć i dłuższe, bardziej złożone fragmenty kodu php, który tak naprawdę generuje zawsze to samo, a przynajmniej nic nie stoi na przeszkodzie aby wygenerowana zawartość odświeżała się powiedzmy raz na godzinę. Czy masz w sidebarze swojego bloga jakiś widget wstawiający zawsze te same reklamy? Dlaczego więc WP miałby przy każdej odsłonie strony odpytywać bazę danych co ma do tego widgetu wstawić?
Mam nadzieję, że już rozumiecie na czym polega problem. A rozwiązaniem jest: cache’owanie fragmentów strony, a nie całości.
Jak to zrobić?
1.
Do swojego pliku functions.php w katalogu skórki dodaj następujący kod:
function mincache($whatto, $howlong = '15', $work = TRUE) { if ($whatto == '') { exit ('Please specify name of cached code'); } if ($howlong == '') $howlong = '15'; $folder = trim(parse_url(get_bloginfo('template_directory'), PHP_URL_PATH), '/'); $cachefile = $folder.'/mincache/'.$whatto.'-cached.html'; $cachetime = $howlong * 60; if ($work == TRUE && file_exists($cachefile) && time() - $cachetime < filemtime($cachefile)) { include($cachefile); echo "\n"; } else { $includedFile = 'inc.'.$whatto.'.php'; ob_start(); include_once($includedFile); $fp = fopen($cachefile, 'w'); fwrite($fp, ob_get_contents()); fclose($fp); ob_end_flush(); } }
2.
W katalogu skórki utwórz katalog o nazwie mincache i nadaj mu uprawnienia do odczytu i zapisu.
3.
Kod, jaki chcesz aby był cache’owany wytnij z pliku php i wklej do nowego pliku i nazwie stworzonej według struktury inc.nazwa.php. Pod nazwa wpisz co chcesz.
4.
W miejsce skąd wyciąłeś ów kod wklej:
mincache('nazwa')
I to wszystko. Teraz zawartość przeniesionego kodu do pliku inc.*.php będzie generowana tylko raz na 15 minut.
* * *
Nieco więcej o stworzonej właśnie funkcji mincache():
mincache($whatto, $howlong, $work)
Jak widać funkcja może przyjmować trzy parametry:
$whatto – nazwa fragmentu kodu który ma być szukany w pliku inc.*.php. Musi więc istnieć plik inc.{$whatto}.php, parametr ten jest bowiem obowiązkowy (inaczej funkcja nie będzie wiedziała co cache’uje.
$howlong – jak długie powinny być odstępy między kolejnymi generowaniami kodu statycznego, w minutach. Domyślnie: 15 minut.
$work – wartość logiczna true/false czy ma próbować pobrać kod z pliku statycznego (true, domyślnie ustawione) czy też za każdym razem generować go od nowa (false). Parametr ten dodałem abyście mogli w czasie prac nad stroną chwilowo wyłączać działanie cache (wartość FALSE).
* * *
I na koniec jeszcze raz konkretny przykład. Załóżmy, że chcemy aby sidebar generował się jedynie raz na pół godziny.
Wykonaj punkty 1 – 2 opisane powyżej.
Otwórz plik sidebar.php, wytnij jego całą zawartość i zastąp:
<?php mincache('sidebar', '30') ?>
Utwórz plik inc.sidebar.php w katalogu skórki i wklej do niego całą zawartość wyciętą przed chwilą z sidebar.php.
I to wszystko. Od teraz sidebar będzie się generował jedynie raz na pół godziny, co na pewno skróci czas ładowania strony.