May 21 2013
How to Cache CakePHP DbAcl, ACO, and ARO checks
After enabling SQL query logging to Chrome Console I began noticing that queries against the ARO table appear running at 300 milliseconds or higher. This is data that doesn’t change often and is needed on every request so its a great candidate for caching. Unfortunately I couldn’t find any mechanism for caching DbAcl checks. Here is my solution.
This is fairly straight forward. First create a new file at app/Lib/CacheDbAcl.php and copy and paste the code in (hyperlink):
Next add the following configurations to app/Config/bootstrap.php:
Now add or edit the following in app/Config/core.php:
The CacheDbAcl library works the exact same as the DbAcl library that is shipped with CakePHP 2.x. The only changes made are to the check() method. What it does:
- CacheDbAcl verifies caching is enabled. If it’s not enabled it just resumes normal operation,
- Reads in the name of the cache config you want to use, see CacheDbAclConfig.
- Checks what portion of the ARO you want to use as your cache key (more on this later), see CacheDbAclAro.
- Checks if an entry for the Aro, Aco, and Action exists in the cache. If not it performs its normal operations and then caches the results. Otherwise it just reads from the cache.
More on the CacheDbAclAro Setting
Since the ARO array passed into DbAcl::check can be quite different depending on your database structure and application requirements I allow you to set exactly which portion of the ARO you want to use as a unique cache key. If you want a cache created for each user, just don’t set this setting at all.
If you only want cache entries created for each group then use something similar to what I posted above. Maybe you have a special use-case and only want it using a very specific portion of the ARO as a key, this gives you that flexibility.
I went with User.UserGroup for this applicaton because our permissions are group based and I wanted to reduce the overall amount of cache entries created. When a group’s permissions are changed the modified field in the UserGroups model will naturally be updated so new cache entries will automatically be created and the old ones will eventually expire.