14 Sep 07 _ Caching Model Data in CakePHP

By casey
in CakePHP, Casey's Corner
A slightly more technical post for those of you who care.
CakePHP is great for a lot of things, but for effeciency it is not. Because of Cake’s smart data organization and recursive model associations, the system will frequently accesses the database several (dozen) more times that it really needs to, potentially dragging down a server if you’re not careful.
Since it’s so easy to access the data you need in Cake, you have to be careful to manage the intrinsic inefficiency in the system. There are some obvious things you can do, such as dynamic model unbinding, specific find calls, and knowing how to set your recursive model associations for specific controllers.
But then there are those times when you really do need to make a massive SQL call. I ran into this problem a week ago while working on Ancient Wisdom’s WebTree CMS application. One of the features of the system is that it auto-generates the main site navigation based on the content’s category structure. Because of this, Cake needs to call a self-joined Category model that is associated with a separate Content model, find all parent categories, all child categories, and then all the pages located inside those child categories to build out the site navigation. So even after paring down all unnecessary associations and grabbing only the necessary table data, a decent sized site (say seven top-level categories) required something like 50 or so queries to the SQL database.
This was clearly unnaceptable, as Cake would need to do this every time a page was loaded, in addition to the SQL calls necessary for the specific page content. The answer?
Caching!
Caching is a very common solution to problems such as these. Why access the same data over and over again when you can access it once, and have it ready to go each time a page is requested?
Cake actually includes some default Cache mechanisms. However, the most useful of these (sitewide view caching), still has a buggy implementation in Cake 1.2. The other option was element caching, where you can cache the rendered view of a specific element for a specified duration.
Neither of these would really work, as it was the results of the SQL query that I needed to parse in several ways.
The solution was to cache the output array of the SQL query, instead of caching a rendered view. That way, the data was there at a moment’s notice, and I could run it through as many functions as needed, without the dozens of SQL queries necessary to grab it in the first place.
The key to this problem is PHP serialize function, which converts (and preserves) the contents and structure of an array into a string. Once you serialize the results of the SQL query, you can write that into a file in Cake’s cache directory, and access it as needed.
We need to make a function that will do one of two things:
- Check to see if a cached data file exists. If it does, open the file, unserialize the array, and return the data.
- If the cached data doesn’t exist, execute the necessary SQL query, write those results to a cached file, and return the data.
To read more about data caching, and to see code examples, stay tuned for part 2 of this post, coming early next week.








