Når man jobber med PHP er det ikke alltid at man trenger å kjøre tunge SQL spørringer mot databasen for hver sidevisning, da flere operasjoner henter opp den samme informasjonen. Da kan man benytte cache. Jeg opprettet meg en enkel Cache klasse, for å illustrere at det egentlig ikke er en tungvindt prosess, samtidig som man enkelt kan se hvordan cache kan benyttes.
Klassen
class Cache {
private $Folder = 'cache/';
public function __construct ($Folder = '') {
if (isset($Folder) && is_dir ($Folder)) $this->Folder = $Folder;
}
private function file ($File) {
return $this->Folder . sha1 ($File) . '.cached';
}
public function get ($File, $TTL = 600) {
$Filepath = $this->file ($File);
if (file_exists ($Filepath) && filemtime ($Filepath) > strtotime ('- ' . $TTL . ' seconds'))
return unserialize (file_get_contents ($Filepath));
return false;
}
public function set ($Filename, $Content) {
$Filepath = $this->file ($Filename);
return file_put_contents ($Filepath, serialize($Content)))
}
public function flush ($Filename) {
$Filepath = $this->file ($Filename);
if (file_exists ($Filepath))
return unlink ($Filepath);
return true;
}
}
Da har man en helt enkel PHP klasse som tar for seg det grunnleggende med Cache. Kort fortalt har man metoder for å hente ut fila, lage ny fil, eller tømme cachen. Problemet til mange er å forstå hvordan man kan benytte en cache. I mitt tilfelle ønsker jeg å lagre cachen som ett array, siden jeg fortsatt skal kunne benytte informasjonen jeg henter opp ifra databasen dynamiskt, selv om at det er ifra cache. I andre tilfeller kan jeg bare lagre hele HTML koden rett i cache, for å spare enda mer datakraft, men da fjerner jeg den dynamiske delen med koden i mitt tilfelle.
En kunde ønsket en FAQ, hvor alle spørsmålene ble listet opp, gruppert etter hvilken kategori de tilhørte, men svarene skulle ikke stå før man valgte å klikke de fram, men siden det var ganske mange kategorier, spørsmål og svar, ønsket dem en cache funksjon på det.
Siden siden skulle være dynamisk for å få fram svarene, tenker man kanskje først at man må cache alle svarene i egne filer, men ved bruk av en array i cachen, trenger man bare én cache fil. Her er hvordan jeg løste det.
$Cache = new Cache;
$CacheName = 'faq';
// Her sjekker jeg opp om det finnes en cache, hvis ikke, så oppretter jeg en cache med ønsket resultat
if (!$Row = $Cache->get ($CacheName)) {
// Det fantes ingen Cache/den var for gammel, derfor henter jeg ut informasjonen ifra databasen
// og oppretter en ny cache fil
$SQL = new SQL (MYSQLHOST, MYSQLUSER, MYSQLPASS, MYSQLDB);
$Query = 'SELECT s.id AS main_id, s.name, a.id, a.title, a.content
FROM faq_sections AS s
INNER JOIN faq_articles AS a ON (s.id = a.section_id)
ORDER BY a.section_id, a.id';
$SQL->query ($Query);
while ($Result = $SQL->fetch_assoc()) {
$Row[] = $Result;
}
$Cache->set ($CacheName, $Row);
// Debug testing
echo '<p>LIVE FROM DATABASE</p>';
}
Nå har jeg enten informasjonen ifra cache, eller databasen, i $Row-arrayen, og kan derfor fortsette med vanlig koding under for å vise fram informasjonen jeg ønsker.
I administrasjonspanelet, kan jeg benytte $Cache->flush (‘faq’) når jeg legger inn nye spørsmål og svar, for å gi en oppdatert side til alle brukerne.
Kom gjerne med spørsmål og forslag til klassen.
Siden du lagrer i en tekstfil, hadde det vært en idé å komprimert innholdet ytterlig med gzencode () / gzcompress() ? Jeg har ikke nyttet meg av disse funksjonene før, så kan ikke si 100 % det vil fungere.
I teorien vil gzencode/gzcompress gjøre prosessen tregere, da man er avhengig av å pakke ut innholdet for hver gang man skal benytte det. Mulig man kan få det til å bli raskere ved å pakke det ned når det kommer opp i ett par MB, men med tekst/arrayer/ren HTML, vil jeg tro at komprimering bare vil bli ett unødvendig ledd som gjør cachingen tregere. Har ikke testet dette ut i praksis, men min teori tilsier at komprimering vil bli en flaskehals.