Published by Rolf on 04 Sep 2010 at 10:18 pm
A simpler NamespaceFile engine for CakePHP 1.2
Using Cake, once you start working with a large number of data cache files, you see the limitation of storing them all in a single directory (which is the default FileEngine behavior). In my case I have a hierarchical Tree behavior on a model and rather than traverse the tree to find its path each time (which incurs a bunch of DB queries), I simply cache the array of its “branch” to save the work. But this means I have a cache file for each node in the tree, and rapidly that gets to be a big number of files in app/tmp.
Frank de Graaf wrote an excellent drop-in upgrade of FileEngine that lets you name the cache keys as namespaces, which get stored in different directories. So you can, for example, delete a group of keys at once by deleting their directory. He doesn’t recommend it for replacing your default FileEngine cache, but for specialized instances (like mine) it works great. One change I did make to his class was to make it extend FileEngine rather than reimplement it like he does – this results in a very compact class that seems to work just as well, as far as I can tell.
To use it, I chose to activate it at runtime, just where I needed it, then switch back to the default. E.g.,
... function function_that_needs_this_cache_engine() { // Use NamespaceFile cache engine, only for this App::import('Vendor', 'NamespaceFile'); Cache::config('app', array( 'engine' => 'NamespaceFile', 'duration'=> '+1 year', 'prefix' => 'data.' )); Cache::write('namespace.cachename', 'cache_value', "+1 year"); echo Cache::read('namespace.cachename'); // revert to the normal cache engine Cache::config('default', array( 'engine' => 'File', 'path' => ROOT . DS . APP_DIR . DS . 'tmp' )); }
The class is here; put it in app/vendors/namespace_file.php:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | <?php /** * Partial reimplementation of Cake's original FileEngine. This * engine supports namespaces similar to: * * Cache::write('app.pictures.recent', $recentPictures, 'app'); * Cache::write('app.pictures.top', $topPictures, 'app'); * * This namespacing allows deletion of parent namespaces like: * * Cache::delete('app.pictures', 'app'); * * The settings for this cache should be * defined at the bottom of /config/bootstrap.php like the following: * * App::import('Vendor', 'NamespaceFile'); * Cache::config('app', array('engine' => 'NamespaceFile', 'duration'=> '+1 hour', 'prefix' => 'cake.')); * * Place this file in APP/vendors/. * * WARNING: DO NOT USE AS YOUR APP'S DEFAULT CACHE! * * @author Frank de Graaf (Phally) * @link http://www.frankdegraaf.net * @license MIT license * * // Modified 9/4/10 by echothis - Changed to extend FileEngine, resulting in a much simpler class */ class NamespaceFileEngine extends FileEngine { /** * Write data for key into cache * * @param string $key Identifier for the data * @param mixed $data Data to be cached * @param mixed $duration How long to cache the data, in seconds * @return boolean True if the data was succesfully cached, false on failure * @access public */ function write($key, &$data, $duration) { $writable =& $this->__setKey($key); if (!is_a($writable, 'File') || !$this->__init || $data === '') { return false; } if (!$writable->exists()) { $writable->Folder->create($this->__getFolderPath($key)); $writable->create(); } parent::write($key, &$data, $duration); } /** * Get absolute file for a given key * * @param string $key The key * @return mixed Absolute cache file for the given key or false if erroneous * @access private */ function __getPath($key) { return $this->settings['path'] . str_replace('.', DS, $key); } /** * Get absolute folder for a given key * * @param string $key The key * @return mixed Absolute cache file for the given key or false if erroneous * @access private */ function __getFolderPath($key) { return $this->__getPath(substr($key, 0, strrpos($key, '.') + 1)); } /** * Return the class (File/Folder) for a key. * * @param string $key The key * @return mixed File or Folder class for a key. * @access private */ function __setKey($key) { return $this->__setPath($this->__getPath($key)); } /** * Return the class (File/Folder) for a path. * * @param string $path The path * @return mixed File or Folder class for a path. * @access private */ function __setPath($path) { $this->__File->Folder->cd($path); if (is_dir($path)) { $object = &$this->__File->Folder; return $object; } $this->__File->path = $path; $object = &$this->__File; return $object; } /** * Override the parents key method, so the keys don't get transformed * * @param string $key The key * @return mixed The key if one is passed else return false * @access public */ function key($key = null) { if (empty($key)) { return false; } return $key; } } ?> |