Find attached a patch file for this.
Thanks,
Tony
On 6/7/2007 1:07 PM, Tony Ford wrote:
Zend_Cache seemed very elegant to me at first, until I tried to make a
customization.
I have some apps that will be using memcached for objects. Thing is,
some of my server farms will have multiple sites and networks, all
using the same pool of memcached servers. Of course all the networks
will cache similar named objects, like 'acl' for instance. So, to
avoid namespace trampling, or rather to "create" namespaces, I thought
it'd be very useful to have cache id prefixes. Now, instead of setting
keys in memecached just called 'obj_name' they'd be
'uniquenetwork_obj_name'. This allows me to have an acl object for
Network1 (network1_acl) and an acl object for network2 (network2_acl).
I could just go ahead and setup a constant and pass it in along with
the ids into every load(), save(), remove(), etc calls, but that seems
like a lot of unnecessary crap. Instead, it makes a lot more sense to
me to create a new backend option for my "cache id prefix", then have
each one of those methods concat the prefix on to the front of ids
automatically just before the real memcache calls are made.
So, I went about this, and its a real mess. First of all, all options
are hardcoded into the classes and get explicitly checked at object
instantiation. OK, well, I extended Zend_Cache_Backend_Memcached and
did this:
public function __construct($options = array())
{
// add cache id prefix as an allowed option, default nothing
$this->_options['cache_id_prefix'] = null;
// Call parent constructor
parent::__construct($options);
}
Then each one of those methods now look basically like this:
public function load($id, $doNotTestCacheValidity = false)
{
$id = $this->_options['cache_id_prefix'] . $id;
parent::load($id, $doNotTestCacheValidity);
}
Overall, I didn't think that was too big of a deal, but then I
realized that the backends are hardcoded and checked in Zend_Cache,
just like the options, so I'd have to do the same thing for that.
What's worse though, is only the name of the backend is passed in, and
then class names are created and called with a hardcoded
'Zend_Cache_Backend' . $backend. Now I can't even call my class
something different. Now I'd have to create my class file specifically
in the /Zend/Cache/Backend directory, and call it something like
CustomMemcached.
Anyway, overall Zend_Cache is a very nice component with lots of
options, and I appreciate all of them, its just that its very closed.
Maybe that was the intention, and if so, maybe you would accept a
patch file from me to officially add this feature to the memcache
backend.
Thanks in advance for reading,
Tony
Index: Memcached.php
===================================================================
--- Memcached.php (revision 264)
+++ Memcached.php (working copy)
@@ -64,6 +64,9 @@
* =====> (boolean) compression :
* true if you want to use on-the-fly compression
*
+ * =====> (string) cache_id_prefix :
+ * prefix for cache ids
+ *
* @var array available options
*/
protected $_options = array(
@@ -72,7 +75,8 @@
'port' => Zend_Cache_Backend_Memcached::DEFAULT_PORT,
'persistent' => Zend_Cache_Backend_Memcached::DEFAULT_PERSISTENT
)),
- 'compression' => false
+ 'compression' => false,
+ 'cache_id_prefix' => null
);
/**
@@ -98,6 +102,11 @@
Zend_Cache::throwException('The memcache extension must be loaded
for using this backend !');
}
parent::__construct($options);
+ if (isset($this->_options['cache_id_prefix'])) { // particular case
for this option
+ if (!preg_match('~^[\w]+$~', $this->_options['cache_id_prefix'])) {
+ Zend_Cache::throwException('Invalid cache_id_prefix : must use
only [a-zA-A0-9_]');
+ }
+ }
if (isset($this->_options['servers'])) {
$value= $this->_options['servers'];
if (isset($value['host'])) {
@@ -131,7 +140,7 @@
if ($doNotTestCacheValidity) {
$this->_log("Zend_Cache_Backend_Memcached::load() :
\$doNotTestCacheValidity=true is unsupported by the Memcached backend");
}
- $tmp = $this->_memcache->get($id);
+ $tmp = $this->_memcache->get($this->_id($id));
if (is_array($tmp)) {
return $tmp[0];
}
@@ -146,7 +155,7 @@
*/
public function test($id)
{
- $tmp = $this->_memcache->get($id);
+ $tmp = $this->_memcache->get($this->_id($id));
if (is_array($tmp)) {
return $tmp[1];
}
@@ -173,7 +182,7 @@
} else {
$flag = 0;
}
- $result = $this->_memcache->set($id, array($data, time()), $flag,
$lifetime);
+ $result = $this->_memcache->set($this->_id($id), array($data, time()),
$flag, $lifetime);
if (count($tags) > 0) {
$this->_log("Zend_Cache_Backend_Memcached::save() : tags are
unsupported by the Memcached backend");
}
@@ -188,7 +197,7 @@
*/
public function remove($id)
{
- return $this->_memcache->delete($id);
+ return $this->_memcache->delete($this->_id($id));
}
/**
@@ -221,5 +230,21 @@
$this->_log("Zend_Cache_Backend_Memcached::clean() : tags are
unsupported by the Memcached backend");
}
}
+
+ /**
+ * Make and return a cache id
+ *
+ * Checks 'cache_id_prefix' and returns new id with prefix or simply the
id if null
+ *
+ * @param string $id cache id
+ * @return string cache id (with or without prefix)
+ */
+ private function _id($id)
+ {
+ if (isset($this->_options['cache_id_prefix'])) {
+ return $this->_options['cache_id_prefix'] . $id; // return with
prefix
+ }
+ return $id; // no prefix, just return the $id passed
+ }
}