Magento – Einen Block cachen

Magento enthält bereits in der Commmunity Version ein sehr umfangreiches Cache Modul.
So werden standardmäßig Konfigurationsparameter, Layout Xmls, Übersetzungen, Daten von Collections oder die Ausgabe einzelner Blöcke gecachet, sofern der Cache einschaltet ist.
Als Cache Backend kann dabei z.B. einfach das Filesystem, APC oder Memcache dienen. Um den Nutzen zu optimieren, sollte man natürlich versuchen, den Cache komplett im Hauptspeicher vorzuhalten.

In der Enterprise Version ist außerdem ein Full Page Cache Modul enthalten, mit dem nochmal erhebliche performance Steigerungen erzielt werden können, da im Idealfall die komplette Seite (bis auf wenige Platzhalter, wie z.B. die Anzeige der Anzahl der Artikel im Warenkorb) aus dem Cache geladen wird. Das heißt, es muss nicht mehr der komplette Dispatch Prozess durchlaufen werden, was die gecachten Seiten natürlich wesentlich schneller macht.
Die Funktionsweise des Fullpage Cache ist sicherlich einen eigenen Artikel wert und soll an dieser Stelle nicht weiter erwähnt werden.

Aber zurück zum Cache Modul der Community Version, insbesondere dem „Blocks HTML output“ Cache.
Auch wenn man es vermuten könnte, standardmäßig wird die HTML Ausgabe eines Blocks in Magento nicht gecachet. Man muss explixit angeben, dass ein Block gecachet werden soll.
In der Community Version von Magento werden in der in der aktuellen Version (1.7.) lediglich folgende Blöcke gecachet:

  • Mage_Catalog_Block_Navigation
  • Mage_Catalog_Block_Product_New
  • Mage_Page_Block_Html_Footer

Um die HTML Ausgabe eines Blocks zu cachen, gibt es zwei Vorgehensweisen (siehe Magento Wiki):

1. Cache für einen Block per Layout XML aktivieren

1
2
3
4
5
6
7
8
9
<layout version="0.1.0">
    <modulname-blockname>
        <reference name="content">
            <block name="modulname-blockname" type="namespace_modulname/blockclass" />
            <action method="setCacheLifetime"><sec>86400</sec></action>
            <!--<action method="setCacheKey"><key>mycachekey</key></action>-->
        </reference>
    </modulname-blockname>
</layout>

2. Cache im Konstruktor des Blocks aktivieren

1
2
3
4
5
6
7
8
9
10
class Namespace_Modulname_Block_Blockname extends Mage_Core_Block_Template
{
    protected $_template = 'namespace/modulname/blockname.phtml';
    protected function _construct()
    {
      $this->addData(array(
            'cache_lifetime'    => 64000,
            'cache_tags'        => array(Mage_Cms_Model_Page::CACHE_TAG), 
       ));
}

Die Cache Lifetime wird dabei in Sekunden angegeben. Wenn man keinen Cache Tag angibt, wird standardmäßig „block_html“ verwendet.
Siehe: Mage_Core_Block_Abstract

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
abstract class Mage_Core_Block_Abstract extends Varien_Object
{
    /**
     * Cache group Tag
     */
    const CACHE_GROUP = 'block_html';
 
    ...
    public function getCacheTags()
    {
        if (!$this->hasData('cache_tags')) {
            $tags = array();
        } else {
            $tags = $this->getData('cache_tags');
        }
        $tags[] = self::CACHE_GROUP; // Standard Cache Tag hinzufügen
        return $tags;
    }

Die Angabe des Cache Tags ist entscheidend, wenn es darum geht, wann der Cache geleert wird.
Im Magento Backend kann man entweder den kompletten Cache oder einzelne Caches leeren.

Folgende Cache Tags sind standardmäßig vorhanden:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Mage_Api_Model_Config::CACHE_TAG                 = 'config_api';
Mage_Adminhtml_Block_Page_Menu::CACHE_TAGS       = 'BACKEND_MAINMENU';
Mage_Api2_Model_Config::CACHE_TAG 		 = 'CONFIG_API2';
Mage_Catalog_Model_Category::CACHE_TAG           = 'catalog_category';
Mage_Catalog_Model_Product_Type_Price::CACHE_TAG = 'PRODUCT_PRICE';
Mage_Catalog_Model_Product::CACHE_TAG            = 'catalog_product';
Mage_CatalogSearch_Model_Query::CACHE_TAG        = 'SEARCH_QUERY';
Mage_Cms_Model_Block::CACHE_TAG     		 = 'cms_block';
Mage_Cms_Model_Page::CACHE_TAG                   = 'cms_page';
Mage_Core_Model_App::CACHE_TAG                   = 'MAGE';
Mage_Core_Model_Config::CACHE_TAG                = 'CONFIG';
Mage_Core_Model_Resource_Db_Collection_Abstract::CACHE_TAG = 'COLLECTION_DATA';
Mage_Core_Model_Store_Group::CACHE_TAG           = 'store_group';
Mage_Core_Model_Store::CACHE_TAG                 = 'store';
Mage_Core_Model_Translate::CACHE_TAG             = 'translate';
Mage_Core_Model_Website::CACHE_TAG               = 'website';
Mage_Eav_Model_Entity_Attribute::CACHE_TAG       = 'EAV_ATTRIBUTE';
Mage_Rss_Block_Catalog_NotifyStock::CACHE_TAG    = 'block_html_rss_catalog_notifystock';
Mage_Rss_Block_Catalog_Review::CACHE_TAG         = 'block_html_rss_catalog_review';
Mage_Rss_Block_Order_New::CACHE_TAG              = 'block_html_rss_order_new';

Verwendet man also das Standard Cache Tag für die Blöcke, so wird der Cache Eintrag des Blocks geleert, wenn der Block Cache geleert wird, oder natürlich wenn der gesamte Cache geleert wird.

Laden des Blocks aus dem Cache

Ob ein Block aus dem Cache geladen werden kann, wird dann hier überprüft:
Mage_Core_Block_Abstract

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
final public function toHtml()
{
    Mage::dispatchEvent('core_block_abstract_to_html_before', array('block' => $this));
    if (Mage::getStoreConfig('advanced/modules_disable_output/' . $this->getModuleName())) {
        return '';
    }
    $html = $this->_loadCache();
    if ($html === false) {
        // Der Block wurde nicht im Cache gefunden
        $translate = Mage::getSingleton('core/translate');
        /** @var $translate Mage_Core_Model_Translate */
        if ($this->hasData('translate_inline')) {
            $translate->setTranslateInline($this->getData('translate_inline'));
        }
 
        $this->_beforeToHtml();
        $html = $this->_toHtml();
        $this->_saveCache($html);
 
        if ($this->hasData('translate_inline')) {
            $translate->setTranslateInline(true);
        }
    }
    $html = $this->_afterToHtml($html);

Cache Inhalt laden
Mage_Core_Block_Abstract

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
protected function _loadCache()
{
    if (is_null($this->getCacheLifetime()) || !Mage::app()->useCache(self::CACHE_GROUP)) {
        return false;
    }
    $cacheKey = $this->getCacheKey();
    /** @var $session Mage_Core_Model_Session */
    $session = Mage::getSingleton('core/session');
    $cacheData = Mage::app()->loadCache($cacheKey);
    if ($cacheData) {
        $cacheData = str_replace(
            $this->_getSidPlaceholder($cacheKey),
            $session->getSessionIdQueryParam() . '=' . $session->getEncryptedSessionId(),
            $cacheData
        );
    }
    return $cacheData;
}

Das Cache Modul ist also sehr einfach zu verwenden und da Magento nicht unbedingt für seine gute Performance bekannt ist, sollte man den Cache eigentlich überall nutzen wo es möglich ist.
Und immer dran denken: Cache me if you can !

Dieser Beitrag wurde unter Magento abgelegt und mit , , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

Die Kommentarfunktion ist geschlossen.