Блочное кэширование html-кода в XSLT
В данной статье будет приведен пример небольшого кастомного php-макроса, с помощью которого можно закешировать определенный html-блок сайта, допустим список разделов каталога. В стандартном xsl шаблоне происходит начальный вызов, xsl:apply-templates, потом полученные xml-данные обрабатываются, далее происходят дополнительные вызовы для получения необходимых данных. Для очень высоко нагруженного сайта, одним из идеальных вариантов было бы кеширование не xml-данных, которые потом еще надо обработать, а итогового html-кода, одного из блоков страницы сайта. Рассмотрим пример метода для реализации нашей задачи:
public function categoryCache(){
$xsltDom = new DomDocument;
$xsltDom->resolveExternals = true;
$xsltDom->substituteEntities = true;
// $filePath - путь к xsl-шаблону трансформации от корня сайта.
$filePath = SYS_XSLT_PATH . '/xsltTpls/leftCache.xsl';
$xsltDom->load($filePath, DOM_LOAD_OPTIONS);
$xslt = new xsltProcessor;
$xslt->registerPHPFunctions();
$xslt->importStyleSheet($xsltDom);
$dom_new = new DOMDocument("1.0", "utf-8");
// $xml - xml-данные для трансформации.
$xml = file_get_contents('udata://catalog/getCategoryList/void/shop/');
$dom_new->loadXML($xml);
//производим трансформацию
$result = $xslt->transformToXML($dom_new);
//html-данные необходимо включить в CDATA и в какой либо корневой узел.
$result = '<udata><![CDATA[' . $result . ']]></udata>';
// данный принцип возвращения данных отключает xslt-трансформацию системой UMI.CMS
return array('plain:result' => $result);
}
Метод можно добавить в файл classes/modules/custom.php, тогда вызов в xsl-шаблоне будет следующим:
<xsl:value-of select="document('udata://custom/categoryCache?expire=36000')/udata" disable-output-escaping="yes" />
Полученный html-код будет закеширован на час, если на сайте включен кеш. В случае необходимости, можно настроить сохранение кеша в текстовый файл на сервере, как это было сделано в данной статье Кеширование результата работы метода getCreateForm в XSL-шаблоне
Пример шаблона leftCache.xsl:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xsl:stylesheet SYSTEM "ulang://i18n/constants.dtd:file">
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xlink="http://www.w3.org/TR/xlink"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:umi="http://www.umi-cms.ru/TR/umi">
<xsl:output encoding="utf-8" method="html" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="." mode="left-column" />
</xsl:template>
<xsl:template match="udata[@method = 'getCategoryList']" mode="left-column">
<ul class="catalog_menu" umi:button-position="bottom left" umi:element-id="{@category-id}" umi:region="list" umi:module="catalog" umi:sortable="sortable">
<xsl:apply-templates select="//item" mode="left-column" />
</ul>
</xsl:template>
<xsl:template match="udata[@method = 'getCategoryList']//item" mode="left-column">
<li umi:element-id="{@id}" umi:region="row">
<span>
<a href="{@link}" umi:field-name="name" umi:delete="delete" umi:empty="&empty-section-name;">
<xsl:value-of select="." />
</a>
</span>
<xsl:apply-templates select="document(concat('udatacache://catalog/getCategoryList/void/', @id))/udata"/>
</li>
</xsl:template>
<xsl:template match="udata[@method = 'getCategoryList']">
<ul umi:element-id="{@category-id}" umi:region="list" umi:module="catalog" umi:sortable="sortable" umi:button-position="top right">
<xsl:apply-templates select="//item" />
</ul>
</xsl:template>
<xsl:template match="udata[@method = 'getCategoryList']//item">
<li umi:element-id="{@id}" umi:region="row">
<a href="{@link}" umi:field-name="name" umi:delete="delete" umi:empty="&empty-section-name;">
<xsl:value-of select="." />
</a>
</li>
</xsl:template>
</xsl:stylesheet>