It is Saturday night and it is raining like it hasn’t rained in weeks. So I decided to spend the night to work on my pet project: MyLyricsFinder.com.
It uses the Zend Framework. The latest addition tonight is Zend_Cache. I added the Top 10 Songs and Artist list in the frontpage – so caching it would make sense. Without the cache, every user that will visit the site will have to query the database. Getting the top 10 list from 200K+ rows is pretty heavy on the resources. Not to mention the overhead it will cause on the user’s side. So I came up with the code below:
//this code snippet is part of my indexAction() in my IndexController //for the cache $frontendOptions = array(); $frontendOptions['lifetime'] = 3600; $frontendOptions['automatic_serialization'] = true;$backendOptions = array(); $backendOptions['cache_dir'] = Zend_Registry::get('cache_dir'); // getting a Zend_Cache_Core object $cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions); // see if a cache already exists: if(!$result_pop_songs = $cache->load('pop_songs')) { //get most popular songs $dbAdapter = Zend_Registry::get('dbAdapter'); $sql = 'SELECT s.song_title, s.song_slug, s.song_counter, at.artist_slug FROM songs_table s LEFT JOIN album_table al ON s.album_id=al.album_id LEFT JOIN artist_table at ON al.artist_id=at.artist_id WHERE s.song_counter>0 ORDER BY s.song_counter DESC LIMIT 10'; $this->view->pop_songs = $dbAdapter->fetchAll($sql); $cache->save($this->view->pop_songs, 'pop_songs'); } else { // cache hit! shout so that we know //echo "This one is from cache!nn"; $this->view->pop_songs = $result_pop_songs; } |
In addition to the Top 10 List in the frontpage, I have also cached the list of Artist per Letter and the List of Albums per Artist. I have reduced the number of database requests significantly – although I don’t know how much – I can tell the difference in load time with and without the cache.
Code Walkthough
$frontendOptions = array(); $frontendOptions['lifetime'] = 3600; $frontendOptions['automatic_serialization'] = true; $backendOptions = array(); $backendOptions['cache_dir'] = Zend_Registry::get('cache_dir'); $cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions); |
This part of the code sets up the Zend_Cache. Most likely, yours will be similar to this. Except for the line with the get(‘cache_dir’). I have set up Zend_Registry::get(‘cache_dir’) in my Bootstrap file to “../tmp/”
if(!$result_pop_songs = $cache->load('pop_songs')) { |
The line above checks if a cache for ‘pop_songs’ already exists. If not, then it will query the database with the code below:
$dbAdapter = Zend_Registry::get('dbAdapter'); $sql = 'SELECT s.song_title, s.song_slug, s.song_counter, at.artist_slug FROM songs_table s LEFT JOIN album_table al ON s.album_id=al.album_id LEFT JOIN artist_table at ON al.artist_id=at.artist_id WHERE s.song_counter>0 ORDER BY s.song_counter DESC LIMIT 10'; $this->view->pop_songs = $dbAdapter->fetchAll($sql); $cache->save($this->view->pop_songs, 'pop_songs'); |
The last line will save the query into the cache. So the next time a user will come, the ‘pop_songs’ cache will already exist in the cache and the code below is executed:
$this->view->pop_songs = $result_pop_songs; |