Простой способ кэширования шаблонов на PHP

в 17:46, , рубрики: php, web-разработка, высокая производительность, кэширование, оптимизация, производительность, метки: , , , ,

Часто при разработке приложений на PHP встаёт вопрос кэширования всего выводимого приложением шаблона, либо какой-то его части, которая довольно статичная во времени. Если при разработке использовался какой-либо шаблонизатор, то данный вопрос решается «из коробки». Но не во всех приложениях на PHP используются шаблонизаторы, а вопрос о кешировании шаблона или его части остаётся открытым. Ниже описан один из вариантов решения данной проблемы.

image

Ниже приведён код реализации класса для кэширования шаблона (далее он будет рассмотрен чуть подробно)

Класс TemplateCache

class TemplateCache
{
    /**
     * @var ICacheDriver
     */
    private $cacheDriver;

    public function __construct($cacheDriver = false, $options=array())
    {
        if(!$cacheDriver){
            $cacheDriver = new ArrayCacheDriver($options);
        }
        $this->cacheDriver = $cacheDriver;
    }

    public function setCacheDriver($cacheDriver)
    {
        $this->cacheDriver = $cacheDriver;
    }


    public function start($id, $group='template')
    {
        $content = $this->cacheDriver->get($id, $group);
        if($content){
            echo $content;
            return true;
        }
        ob_start();
        return false;
    }

    public function end($id, $group='template')
    {
        $content = ob_get_contents();
        $this->cacheDriver->store($id, $group, $content);
        ob_end_clean();
        echo $headerContent;
    }

    public function clean($group=false, $id=false)
    {
        this->cacheDriver->clean($group, $id);
    }

}

Данный класс работает следующий образом — кэширование запускается методом start. Если кэшируемый блок присутствует в кэше — то выводим его, получив из кэша, если нет — кешируем блок (или целую страницу) шаблона. Кеширование заканчивается по вызову метода end.
Работа класса основывается на буферизации вывода, расположенного между вызовами данных 2 методов и сохранении данного буфера в кэш.
Работа с хранилищем кэша инкапсулируется в отдельном классе, объект которого создаётся и передаётся в класс TemplateCache.
Данный класс должен реализовывать интерфейс ICacheDriver, приведённый ниже.

Интерфейс ICacheDriver

interface ICacheDriver
{
    public function store($id, $group, $data);
    public function get($id, $group);
    public function clean($group, $id);
}

Реализация ICacheDriver классом MemcachedCacheDriver

class MemcachedCacheDriver implements ICacheDriver
{
    private $memcache;
    private $server = "localhost";
    private $port = 11211;
    private $expires = 600;

    public function __construct($options=array())
    {
        $this->server = isset($options['server']) ? $options['server'] : $this->server;
        $this->port = isset($options['port']) ? $options['port'] : $this->port;
        $this->expires = isset($options['expires']) ? $options['expires'] : $this->expires;

        $this->memcache = new Memcache();
        $this->memcache->connect($this->server, $this->port);
    }

    public function store($id, $group, $data)
    {
        $this->memcache->set($this->prepareKey($id, $group), $data, MEMCACHE_COMPRESSED, $this->expires);
    }

    public function get($id, $group)
    {
        return $this->memcache->get($this->prepareKey($id, $group));
    }

    public function clean($group, $id)
    {
        if(!$group && !$id){
            $this->memcache->flush();
            return;
        }

        if(!$id){
            //TO DO: develop delete cache by group
            return;
        }

        $this->memcache->delete($this->_getKey());
    }

    protected function prepareKey($id, $group)
    {
        return $group . ':' . $id;
    }

}

Ниже приведён пример использования класса для кеширования шаблона.

Пример использования TemplateCache в шаблоне

<?php if(!$templateCache->start('links', 'startPage')): ?>
 <dl>
<dt><a href='/manual/en/getting-started.php'>Getting Started</a></dt>
	<dd><a href='/manual/en/introduction.php'>Introduction</a></dd>
	<dd><a href='/manual/en/tutorial.php'>A simple tutorial</a></dd>
<dt><a href='/manual/en/langref.php'>Language Reference</a></dt>
	<dd><a href='/manual/en/language.basic-syntax.php'>Basic syntax</a></dd>
	<dd><a href='/manual/en/language.types.php'>Types</a></dd>
	<dd><a href='/manual/en/language.variables.php'>Variables</a></dd>
	<dd><a href='/manual/en/language.constants.php'>Constants</a></dd>
	<dd><a href='/manual/en/language.expressions.php'>Expressions</a></dd>
	<dd><a href='/manual/en/language.operators.php'>Operators</a></dd>
	<dd><a href='/manual/en/language.control-structures.php'>Control Structures</a></dd>
	<dd><a href='/manual/en/language.functions.php'>Functions</a></dd>
	<dd><a href='/manual/en/language.oop5.php'>Classes and Objects</a></dd>
	<dd><a href='/manual/en/language.namespaces.php'>Namespaces</a></dd>
	<dd><a href='/manual/en/language.exceptions.php'>Exceptions</a></dd>
	<dd><a href='/manual/en/language.generators.php'>Generators</a></dd>
	<dd><a href='/manual/en/language.references.php'>References Explained</a></dd>
	<dd><a href='/manual/en/reserved.variables.php'>Predefined Variables</a></dd>
	<dd><a href='/manual/en/reserved.exceptions.php'>Predefined Exceptions</a></dd>
	<dd><a href='/manual/en/reserved.interfaces.php'>Predefined Interfaces and Classes</a></dd>
	<dd><a href='/manual/en/context.php'>Context options and parameters</a></dd>
	<dd><a href='/manual/en/wrappers.php'>Supported Protocols and Wrappers</a></dd>
</dl>
<?php $templateCache->end('links', 'startPage'); endif; ?>

В итоге, получен удобный класс для прозрачного и незагромождающего шаблоны кэширования блоков HTML-кода.
Буду рад увидеть Вас в комментариях со своими предложениями и замечаниями.
Спасибо

Автор: andrewnester

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js