Блочное кеширование html-кода в XSLT
Материал из Umicms
В данной статье будет приведен пример небольшого кастомного php-макроса, с помощью которого можно закешировать определенный html-блок сайта, допустим список разделов каталога. В стандартном xsl шаблоне происходит начальный вызов, xsl:apply-templates, потом полученные xml-данные обрабатываются, далее происходят дополнительные вызовы для получения необходимых данных. Для очень высоко нагруженного сайта, одним из идеальных вариантов было бы кеширование не xml-данных, которые потом еще надо обработать, а итогового html-кода, одного из блоков страницы сайта. Рассмотрим пример метода для реализации нашей задачи:
public function categoryCache(){ $xsltDom = new DomDocument; $xsltDom->resolveExternals = true; $xsltDom->substituteEntities = true; // $filePath - путь к xsl-шаблону трансформации. $filePath = CURRENT_WORKING_DIR . '/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-шаблоне . Пример метода, для кеширования данных в html-файл:
public function getCategoryListCustom(){ $folder = CURRENT_WORKING_DIR . '/sys-temp/udatacache/'; $path = $folder . 'left-columnCache.xml'; if(!is_dir($folder)) mkdir($folder, 0777, true); if(is_file($path)) $mtime = filemtime($path); $expire = 86400; if(!is_file($path) || time() > ($mtime + $expire)) { $xsltDom = new DomDocument; $xsltDom->resolveExternals = true; $xsltDom->substituteEntities = true; // $filePath - путь к xsl-шаблону трансформации. $filePath = CURRENT_WORKING_DIR . '/xsltTpls/modules/catalog/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 mode=\"cache\"><![CDATA[" . $result . "]]></udata>"; file_put_contents($path, $result); // данный принцип возвращения данных отключает xslt-трансформацию системой UMI.CMS return array('plain:result' => $result); }else{ $result = file_get_contents($path); return array('plain:result' => $result); } }
Пример шаблона 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>
