Für umfangreichere Datenkonstrukte, die häufig verwendet werden oder aber aufwändig zu erzeugen sind, ist ein Cache nützlich. Ein typischer Fall sind Dateilisten, die sich auf Verzeichnissen generieren (z.B. für eine einfache Bildergalerie). Die Inhalte der Verzeichnisse ändern sich meist nur extrem selten – wozu also immer wieder aufs Neue via Dateisystem auslesen, welche Dateien existieren? Hier ist es doch naheliegender, die Liste zu cachen und nur selten oder gar nur via gezielter Anforderung zu aktalisieren.
Einen von vielen Fällen, wo das Caching Framework in einer eigenen Extension zum Einsatz kommen kann…
Dieser Artikel befasst sich mit der Nutzung in TYPO3 Versionen 4.3 – 4.5. In Versionen seit 4.6 vereinfacht sich die Nutzung.
Nachdem LTS-Version (4.5) bei uns gerne noch für große Projekte genutzt wird, und gerade bei großen Projekten die Performance eine (größere) Rolle spielt, halte ich einen Artikel über die „umständlichere“ Nutzung dennoch für sinnvoll.
Schrittweise
- Cache-Tabellen anlegen
- Cache definieren
- Cache (für das Backend) registrieren / Garbage collector
- Cache instanziieren
- Cache nutzen
Cache-Tabellen anlegen
Ab TYPO3 4.6 kann man sich dies sparen…
# TABLE STRUCTURE FOR TABLE 'tx_myext_mycache'
#
CREATE TABLE tx_myext_mycache (
id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
identifier VARCHAR(250) DEFAULT '' NOT NULL,
crdate INT(11) UNSIGNED DEFAULT '0' NOT NULL,
content mediumblob,
lifetime INT(11) UNSIGNED DEFAULT '0' NOT NULL,
PRIMARY KEY (id),
KEY cache_id (identifier)
) ENGINE=InnoDB;
#
# TABLE STRUCTURE FOR TABLE 'tx_myext_mycache_tags'
#
CREATE TABLE tx_myext_mycache_tags (
id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
identifier VARCHAR(250) DEFAULT '' NOT NULL,
tag VARCHAR(250) DEFAULT '' NOT NULL,
PRIMARY KEY (id),
KEY cache_id (identifier),
KEY cache_tag (tag)
) ENGINE=InnoDB;
Cache definieren
Dieser Teil wäre ab 4.6 deutlich kürzer…
// Register cache 'myext_mycache'
if (!is_array($TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations']['myext_mycache'])) {
$TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations']['myext_mycache'] = array();
}
// Define string frontend as default frontend, this must be set with TYPO3 4.5 and below
// and overrides the default variable frontend of 4.6
if (!isset($TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations']['myext_mycache']['frontend'])) {
$TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations']['myext_mycache']['frontend'] = 't3lib_cache_frontend_StringFrontend';
}
if (t3lib_div::int_from_ver(TYPO3_version) < '4006000') {
// Define database backend as backend for 4.5 and below (default in 4.6)
if (!isset($TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations']['myext_mycache']['backend'])) {
$TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations']['myext_mycache']['backend'] = 't3lib_cache_backend_DbBackend';
}
// Define data and tags table for 4.5 and below (obsolete in 4.6)
if (!isset($TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations']['myext_mycache']['options'])) {
$TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations']['myext_mycache']['options'] = array();
}
if (!isset($TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations']['myext_mycache']['options']['cacheTable'])) {
$TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations']['myext_mycache']['options']['cacheTable'] = 'tx_myext_mycache';
}
if (!isset($TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations']['myext_mycache']['options']['tagsTable'])) {
$TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations']['myext_mycache']['options']['tagsTable'] = 'tx_myext_mycache_tags';
}
}
Cache (für das Backend) registrieren / Garbage collector
Einige Cache-Backends halten sich selbst sauber, d.h. räumen selbstständig indem sie abgelaufene Inhalte löschen. Für manche ist dies leider nicht der Fall, sodass hier die Aufräumarbeiten angestoßen werden müssen. Hierfür sind zwei Dinge sinnvoll: zum einen das Einrichten des Scheduler Tasks , zum anderen das Registrierung des Caches, damit er im TYPO3-Backend mit dem „Cache löschen“-Button mit geleert wird.
if (TYPO3_UseCachingFramework) {
// register the cache in BE so it will be cleared with "clear all caches"
try {
$GLOBALS['typo3CacheFactory']->create(
'myext_mycache',
$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['myext_mycache']['frontend'],
$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['myext_mycache']['backend'],
$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['myext_mycache']['options']);
} catch (t3lib_cache_exception_DuplicateIdentifier $e) {
// do nothing, a myext_mycache cache already exists
}
}
Cache instanziieren
class tx_myext_myFunctionality {
/**
* @var t3lib_cache_frontend_AbstractFrontend
*/
protected $cacheInstance;
/**
* Constructor
*/
public function __construct() {
$this->initializeCache();
}
/**
* Initialize cache instance to be ready to use
*
* @return void
*/
protected function initializeCache() {
t3lib_cache::initializeCachingFramework();
try {
$this->cacheInstance = $GLOBALS['typo3CacheManager']->getCache('myext_mycache');
} catch (t3lib_cache_exception_NoSuchCache $e) {
$this->cacheInstance = $GLOBALS['typo3CacheFactory']->create(
'myext_mycache',
$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['myext_mycache']['frontend'],
$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['myext_mycache']['backend'],
$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['myext_mycache']['options']
);
}
}
}
Cache nutzen
protected function getCachedMagic() {
$cacheIdentifier = $this->calculateCacheIdentifier();
// If $entry is null, it hasn't been cached. Calculate the value and store it in the cache:
if (FALSE === ($entry = $GLOBALS['typo3CacheManager']->getCache('myCache')->get($cacheIdentifier))) {
$entry = $this->calculateMagic();
// [calculate lifetime and assigned tags]
// Save value in cache
$GLOBALS['typo3CacheManager']->getCache('myCache')->set($cacheIdentifier, $entry, $tags, $lifetime);
}
return $entry;
}