The Source
This tip is not new. It is taken directly from the Zend Framework Documentation at: Zend Framework Performance Guide and I used what was written with few things I’ve skip.
Use Zend_Loader and Remove All require_once
We can’t actually remove all require_once statements. We must have at least one require_once to load the Zend_Loader. First, activate Zend Loader.
require_once 'Zend/Loader.php'; Zend_Loader::registerAutoload();
Next would be removing all require_once statements on all files inside the Zend directory. If you are using Eclipse PDT, you can use the find and replace function.
In your Eclipse IDE, select the Zend directory. Next, press CTRL + H and type require_once on the containing text field. In the scope fields, select Selected Resources to search only on Zend directory. Press Replace.
After the long search, Eclipse will display this dialog.
On the With field, type //require_once. That would comment out all occurrences of require_once in the Zend Framework library. Press OK to finish.
An you are done!
Cache Zend_Db_Table MetaData with Zend_Cache
When you are using Zend_Db_Table (I sometimes only used Zend_Db) you will notice that when you try to retrieve data from the database, the first query called is to DESCRIBE the table. Zend_Db_Table uses the information on DESCRIBE query to do its magic on SELECT.
As I have profiled my queries, I noticed that DESCRIBE query is the longest query (in most cases) which mean a big overhead over you retrieval operation. You have two options:
- Don’t use Zend_Db_Table (go for Zend_Db)
- Cache the MetaData
On this post, I’ll use the caching of MetaData. On your bootstrap file, put this piece of code:
//Caching $frontendOptions = array( 'lifetime' => 25200, 'automatic_serialization' => true ); $backendOptions = array( 'cache_dir' => APPLICATION_PATH . '/tmp' ); $cache = Zend_Cache::factory( 'Core', 'File', $frontendOptions, $backendOptions ); //Cache table metadata Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);
The code simply instructs Zend_Db_Table_Abstract to cache the result of DESCRIBE statement so that next time you retrieve data, the cache is used instead of repeatedly describing tables over and over again.
(But I noticed that INSERT and UPDATE statements don’t have DESCRIBE…)
After several tries with this caching, you will see files on the tmp folder like this: zend_cache—internal-metadatas—5e7576e3cd79114d46850714e998a3b0.
Still there is an overhead on reading the cache file. If you want better caching, use memory based caching like MemCache.
Cache Plugin Loader Class File
When using a plugin, Zend Framework includes several files depending on the plugin used and process several iterations to find the right plugin and include it. With code code below, it creates a list of include_once statements to include those plugin files. Just include this piece of code to your bootstrap.
//Plugin Loader caching $classFileIncCache = APPLICATION_PATH . '/data/pluginLoaderCache.php'; if (file_exists($classFileIncCache)) { include_once $classFileIncCache; } Zend_Loader_PluginLoader::setIncludeFileCache($classFileIncCache);
Caching Your Data
Caching your data will be the most important part of optimization which will save you a lot of database access when repeatedly accessed data are already cache. It is important to set the cache expiration time and also clear the cache when data changes. A simple caching is shown below.
On your bootstrap:
//Caching $frontendOptions = array( 'lifetime' => 25200, 'automatic_serialization' => true ); $backendOptions = array( 'cache_dir' => APPLICATION_PATH . '/tmp' ); $cache = Zend_Cache::factory( 'Core', 'File', $frontendOptions, $backendOptions ); $registry->set('cache', $dbCache);
It creates a cache object with specified expiration time in seconds. Then it puts the cache object to the registry so that you can access them on any part of the project.
We can apply caching heavily on models. The code below demonstrates how to cache the database result. First it gets the data from the cache. If data exists in cache, return it, otherwise get the data from the database, cache it and return it.
public function getAll() { $ret = null; $cache = Zend_Registry::get('cache'); $result = $cache->load(md5('TEST_GETALL')); if(!$result) { $table = $this->_getTable(); $res = $table->fetchAll(); if ($res) { $ret = $res->toArray(); $cache->save($ret, md5('TEST_GETALL')); return $ret; } } else { return $result; } return false; }
You noticed that the cache ID is a hashed version of ‘TEST_GETALL’. I applied md5 hashing on the cache ID for security reasons. The important part of that codes are:
$cache->load() and $cache->save()
If it is time to clear the cached data (when data changed), the code will be like below:
public function clearGetAllCache() { $cache = Zend_Registry::get('cache')->remove(md5('TEST_GETALL')); }
I make it a separate function so that I can call it anywhere in the class like in ADD, EDIT or DELETE processes.
Wonderful blog post about wordpress! Informational and well written. I think I could learn a thing or two from the way you set up your blog. I have subscribed to your rss feed and bookmarked your blog on delicious. I have a blog about SEO and social media that you are welcome to comment on if you find something that intrigues you.