I've written some month ago a little system to assign memcache items tags. So it's possible to invalidate all items which owns a tag by invalidating this special tag.
I think it will be very helpful to migrate this code directly into the memache bundle.
<?php
namespace Geistert\Utility\Memcache;
use Lsw\MemcacheBundle\Cache\MemcacheInterface;
/**
* Memcache Wrapper to use custom tags for items.
*/
class MemcacheManager
{
/**
* @var MemacheInterface
*/
private $memache;
/**
* Cache of Tag values.
*
* @var array
*/
private $tagCache;
const TAGPREFIX = 'MEMCACHEMANAGERTAG__';
/**
* Inititialize Memcache Manager with custom memcache instance.
*
* @param MemcacheInterface $memcache Memache instance
*/
public function __construct(MemcacheInterface $memcache)
{
$this->memcache = $memcache;
$this->tagCache = array();
}
/**
* Native memcache get method.
*
* @param string $name name of item
*
* @return mixed item value
*/
public function get($name)
{
return $this->memcache->get(sha1($name));
}
/**
* Get item from memcache and validate custom tags.
*
* @param string $name name of item
*
* @return mixed item value
*/
public function load($name)
{
if ($item = $this->get($name)) {
if ($item instanceof MemcacheData) {
if ($this->isValid($item)) {
return $item->getData();
}
} else {
return $item;
}
}
return false;
}
/**
* Save item with custom tags.
*
* @param string $key Name of item
* @param mixed $value Value of item
* @param array $tags
* @param int $time Time to live in secounds
*/
public function save($key, $value, $tags = array(), $time = 0)
{
$tagList = array();
foreach ($tags as $tag) {
if ($tagValue = $this->getTagValue($tag)) {
$tagList[$tag] = $tagValue;
} else {
$tagList[$tag] = $this->flushTag($tag);
}
}
$memObject = new MemcacheData($value, $tagList);
$this->memcache->set(sha1($key), $memObject, null, $time);
}
/**
* Flush a single tag.
*
* @param string $tagName Name of Tag
*
* @return int new tag id
*/
public function flushTag($tagName)
{
$rand = rand(1, 300000);
$this->memcache->set(self::TAGPREFIX.$tagName, $rand);
$this->tagCache[$tagName] = $rand;
return $rand;
}
/**
* Check if Item is valid.
*
* @param MemcacheData $item MemcacheData Object with tags
*
* @return bool Is item valid?
*/
private function isValid(MemcacheData $item)
{
foreach ($item->getTags() as $tag => $value) {
if ($this->getTagValue($tag) != $value) {
return false;
}
}
return true;
}
/**
* Get id of a tag. Use internal caching.
*
* @param string $tag Tag name
*
* @return int tag id
*/
private function getTagValue($tag)
{
if (array_key_exists($tag, $this->tagCache)) {
return $this->tagCache[$tag];
} else {
$tagValue = $this->memcache->get(self::TAGPREFIX.$tag);
$this->tagCache[$tag] = $tagValue;
return $tagValue;
}
}
}
<?php
namespace Geistert\Utility\Memcache;
/**
* Memache data wrapper object.
*/
class MemcacheData
{
/**
* Real data of item.
*
* @var mixed
*/
private $data;
/**
* Array of tags.
*
* @var array
*/
private $tags;
/**
* Init Data wrapper.
*
* @param mixed $data item data
* @param array $tags array of tags
*/
public function __construct($data, $tags = array())
{
$this->data = $data;
$this->tags = $tags;
}
/**
* Get item value.
*
* @return mixed item value
*/
public function getData()
{
return $this->data;
}
/**
* Set item value.
*
* @param mixed $data item value
*
* @return self
*/
public function setData($data)
{
$this->data = $data;
return $this;
}
/**
* Get item tags.
*
* @return array tags
*/
public function getTags()
{
return $this->tags;
}
/**
* Set tags of item.
*
* @param array $tags tags of item
*
* @return self
*/
public function setTags($tags)
{
$this->tags = $tags;
return $this;
}
}
I've written some month ago a little system to assign memcache items tags. So it's possible to invalidate all items which owns a tag by invalidating this special tag.
I think it will be very helpful to migrate this code directly into the memache bundle.