3

I'm looking to implement a cache within Zend_Db, there isn't any native method to provide a cache to Zend_Db, so I'm wondering where should I do it.

I took a look to the Zend_Db_Table_Abstract (I'm extending it in a custom App_Model_DbTable_Abstract) and I found a protected method _fetch() which directly take a Zend_Db_Table_Select instance and looks like to be the last step before the adapter.

I was thinking override this method, serialize the $select object, hash it, and finally cache it, and check against each $select object provided to return the cache or an up-to-date rowset.

Is it a correct way to do?

Here is what I just did:

class App_Model_DbTable_Abstract extends Zend_Db_Table_Abstract
{
    protected function _fetch(Zend_Db_Table_Select $select)
    {
        $hashedQuery = sha1(serialize($select->__toString()));
        $cacheManager = Zend_Registry::get('Zend_Cache_Manager');
        $cache = $cacheManager->getCache('database');
        if (!($data = $cache->load($hashedQuery))) {
            $data = parent::_fetch($select);
            $cache->save($data, $hashedQuery);
        }
        return $data;
    }
}
John
  • 119
  • 5

2 Answers2

3
    public function indexAction()
        {
            // action body
            $this->_helper->layout->setLayout('layout');

            $db = new Zend_Db_Adapter_Pdo_Mysql(array('host' => 'localhost',
                                  'username' => 'root',
                                  'password' => '',
                                      'dbname' => 'zendtest'));
            $sql  = "SELECT SQL_CALC_FOUND_ROWS "
                      . "       register.firstname, "
                      . "       register.lastname, "
                      . "       register.username, "
                      . "       register.password, "
                      . "       register.email, "
                      . "       register.city, "
                      . "       register.state, "
                      . "       register.contactno "     
                      . "  FROM register register "
                      . "  WHERE register.id = ? ";                               

                $result = $db->fetchall($sql,1);    

                        $result1 = "";
               $cache = Zend_Registry::get('cache');

                if(!$result1 = $cache->load('mydata2')) {
                    echo 'caching the data…..';
                    $cache->save($result, 'mydata2');
                   } else {
                    echo 'retrieving cache data…….';
                    Zend_Debug::dump($result1);
                  }
}

define cache array in bootstrap file then using zend DB get the data from the database and store it in cache... next time you don't need to get data from db . you can easily and fast access that data from the cache.

vivek s vamja
  • 1,001
  • 10
  • 11
3

As far as I know, the zf create db-table <name> will always create a class inheriting Zend_Db_Table_Abstract which would make your proposal difficult to manage.

Besides, you're coupling the cache & db modules of ZF so one could argue that it's not right to place cache mechanisms under the dbtable scope. For example: you should not know where the data is being fetched from but still be able to cache it, so the process becomes this:

  1. check cache for data, serve if found
  2. fetch data from X (could be dbtable, could also be a Service, an XML-file, some JSON etc)
  3. save data in cache and serve data

So although your solution makes sense now since you're only using dbtable models, it could be placed in a more suiting layer. I would check out http://www.slideshare.net/weierophinney/playdoh-modelling-your-objects-1766001 (around slide #35) for a practical solution.

Summary: the dbtable module and your code concerning it should always be about using the db.

chelmertz
  • 20,399
  • 5
  • 40
  • 46
  • Thank you for your answer, after reading the slide, I think decorators will do the trick, since I sometimes bypass controllers when only accessing model in views, and I wouldn't like to implement my cache there, but a decoated object is ok since the caching is not done in the views, and/or controllers. – John Oct 11 '10 at 10:06
  • @John: good luck! I'm not sure I agree with calling models in views but as long as you feel comfortable with it.. :) (My view on views is that they're supposed to be dumb and just accept whatever data being thrown at theme - i.e. they shouldn't know about anything but the simplest methods of your models). – chelmertz Oct 11 '10 at 13:56