问题
I use Stacic Page Cache (with cache action helper) to cache most of the pages of my App.
This is extremly fast, but not always suitable.
- How do you cache pages with dynamic data? Eg. layout contains info specific to user.
One solution I considered is to load additional data via Ajax. But in my case it would be better to cache parts of the pages (eg. list of entries or sidebar partial).
- Is there any ZF recommended way to do it? Eg. cache the view only, not the layout or vice versa.
Cache action helper provides nice interface to cache all the actions. Any solution to cache the page content or partials or view helpers?
回答1:
What I've been doing lately is creating a service and then configuring that service with both a db connection and a cache object. Retrieving the data uses a kind of "lazy-loading cascade", looking first in memory, then in cache, then to the db.
For example, one of my apps is for a real-estate agency that operates in several - but not all - of the provinces in our country. We have a db-table of provinces, some of which are enabled for the front-end, and we need to render them in various places (say, as options in a select element). We do something like this (the legacy code-base on which I am working uses DAO objects for db access and PEAR's Cache_Lite for caching, so the example is not strictly Zend Framework, but the principle applies equally):
/**
* A service for fetching provinces
*/
class My_Service_Provinces
{
protected $_daoProvinces;
protected $_provinces = array();
protected $_cache;
public function __construct($daoProvinces)
{
$this->setDaoProvinces($daoProvinces);
}
public function setDaoProvinces($daoProvinces)
{
$this->_daoProvinces = $daoProvinces;
return $this;
}
public function getDaoProvinces()
{
return $this->_daoProvinces;
}
public function setCache($cache)
{
$this->_cache = $cache;
return $this;
}
public function getCache()
{
if (null == $this->_cache){
$this->_cache = new My_Cache_Provinces();
}
return $this->_cache;
}
public function getProvinces()
{
if (null == $this->_provinces){
$cache = $this->getCache();
$data = $cache->get();
if (!$data){
$dao = $this->getDaoProvinces();
$rows = $dao->frontend();
$data = array();
while ($row = $rows->get_row()){
$data[$row['provinceId']] = $row;
}
$cache->save(serialize($data));
} else {
$data = unserialize($data);
}
$this->_provinces = $data;
}
return $this->_provinces;
}
public function getProvince($provinceId)
{
$provinces = $this->getProvinces();
return isset($provinces[$provinceId]) ? $provinces[$provinceId] : null;
}
}
The cache object is pre-configured with whatever lifetime is appropriate. I give a long lifetime to seldom-changing data, shorter lifetimes to frequently-changing data. If I really need the change to the data to be immediately available to the app - say, the admin adds a new province - I instantiate the cache object and clear the cache on update.
I've even added a factory to help instantiate the service so that calling code does not have to sweat the dependencies. Calling code - perhaps in a controller or even in a view or view-helper - looks something like:
$service = My_Service_Factory::getService('provinces');
$provinces = $service->getProvinces();
Knowwhatimsayin'?
来源:https://stackoverflow.com/questions/3493900/zf-how-to-cache-parts-of-the-layout