Adding caching to Zend_Db_Table_Abstract
classes is really easy.
- Setup caching in Bootstrap
- Modify all your
class foo extends Zend_Db_Table_Abstract
to class foo extends CachingTable
- Create
class CachingTable extends Zend_Db_Table_Abstract
and overwrite methods update
, insert
, delete
, fetchRow
and fetchAll
- Bring caching object from bootstrap to
init
method
- Create _purgeCache() or similar method which cleans cache
- Use for example
md5($where->__toString())
as caching identifier in fetchAll
and fetchRow
- Call
$this->_purgeCache()
on update
, insert
and delete
- You can also add those caching "categorys" easily using table name as category so you don't have to clear all cached data at once.
Example code:
This example caches all select queries indefinitely and any insert/update/delete purges all cached stuff.
To Bootstrap:
// Caching
$cache_config = new Zend_Config_Ini(dirname(__FILE__) . '/../config.ini', 'cache');
$frontendOptions = array(
'caching' => true,
'lifetime' => null,
'automatic_serialization' => true
);
$backendOptions = array(
'cache_dir' => $cache_config->directory,
'cache_file_umask' => 0607
);
$cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);
Zend_Registry::set('Cache', $cache);
Where you keeps your extensions:
class CachingTable extends Zend_Db_Table_Abstract
{
/**
* @var Zend_Cache
*/
protected $_cache = null;
/**
* @var bool
*/
public $cache_result = true;
/**
* Initialize
*/
public function init()
{
// Get from bootstrap
$this->_cache = Zend_Registry::get('Cache');
} // /function
/**
* Reset cache
*/
public function _purgeCache()
{
$this->_cache->clean(Zend_Cache::CLEANING_MODE_ALL);
} // /function
/**
* update
*/
public function update(array $data, $where)
{
parent::update($data, $where);
$this->_purgeCache();
} // /function
/**
* insert
*/
public function insert(array $data)
{
parent::insert($data);
$this->_purgeCache();
} // /function
/**
* delete
*/
public function delete($where)
{
parent::delete($where);
$this->_purgeCache();
} // /function
/**
* Fetch all
*/
public function fetchAll($where = null, $order = null, $count = null, $offset = null)
{
$id = md5($where->__toString());
if ((!($this->_cache->test($id))) || (!$this->cache_result))
{
$result = parent::fetchAll($where, $order, $count, $offset);
$this->_cache->save($result);
return $result;
}
else
{
return $this->_cache->load($id);
}
} // /function
/**
* Fetch one result
*/
public function fetchRow($where = null, $order = null)
{
$id = md5($where->__toString());
if ((!($this->_cache->test($id))) || (!$this->cache_result))
{
$result = parent::fetchRow($where, $order);
$this->_cache->save($result);
return $result;
}
else
{
return $this->_cache->load($id);
}
} // /function
} // /class
Where you keep database-related stuff:
/**
* Pages
*/
class Pages extends CachingTable
{
/**
* Table name
* @var string
*/
protected $_name = 'PAGES';
/**
* Primary key
* @var string
*/
protected $_primary = 'name';
} // /class
In your actual controller / model / view / whatever:
$pages = new Pages();
//$pages->cache_result = false; // Don't cache
$select = $pages->select();
$select->from($pages, array('content'));
$select->where('name = ?', $page);
$info = $pages->fetchRow($select);
if(!is_null($info))
{
$info = $info->toArray();
}
else
{
// Add new page
$pages->insert(array('name' => $page, 'added' => new Zend_Db_Expr('NOW()'), 'updated' => new Zend_Db_Expr('NOW()')));
}