CakePHP RemoveCache Shell - Remove Your Cache Files Easily
Posted on 4/6/09 by Tim Koschützki
Hey folks,
it's been a while since the last post here on Debuggable. However, this ends now and apart from this very post here we have something bigger brewing for you as well. So please stay tuned a little longer. :)
Anyways, on to some Caching fun.
The Motivation
1. When you work with large projects you can end up with a ton of cache files (models, db cache, etc.) as well as view caching files. When you try removing them with:
cd /app/tmp/cache/models && rm -f cake_*
and
cd /app/tmp/cache/views && rm -f *
.. you can end up with with the "argument list too long" error easily.
2. Also, executing two commands sucks - we are lazy after all. Now you could pull out some fancy bash fun to pipe file names. Have a look at this:
find . -type f | awk '!/empty/ {print "rm", $0}' | bash
The problem is, when you run this in /app/tmp it will not only remove cache files, but also files in /tmp/sessions, /tmp/logs and so on. If you ask me, the command is complex enough, so no need to add more funny stuff there to take this into account.
(For you peeps who want to see this, I bugged Felix to tell me: find . -type f | awk '!/empty$|^.\/logs|^.\/sessions/ {print "rm", $0}' | bash)
3. Once you are on windows, you do not have a powerful bash to your side.
I thought a simple call to a CakePHP shell can do the trick as well and doesn't force you to waste half a minute to remember and type in the proper bash command.
The Solution
The RemoveCache shell allows you to remove your cae cache files easily. It takes two parameter:
- A boolean to control if you want to remove standard cache files (models, db cache, etc.)
- A regex pattern to control which view cache files to remove
Here are some common usage scenarios:
Usage: cake remove_cache <std_cache_boolean> <pattern_to_match_viewcache_files>
Usage: cake remove_cache // removes all cache files
Usage: cake remove_cache 0 // removes only view cache files
Usage: cake remove_cache 0 home // removes only the view cache file for your homepage
Usage: cake remove_cache 0 articles_ // removes all view cache files for your articles controller
Usage: cake remove_cache 1 /letter_z$/ // removes all std cache files and view cache files ending with 'letter_z'
I did not put in a pattern for standard cache files, because most of the time you cannot remember your cache keys anyways and most of the time it doesn't harm if a cache file is invalidated to rebuilt the cache. If someone wants a pattern for that too, because they have long-taking queries, just comment and I will add it.
By default, the shell looks in your standard /app/tmp directory (plus subfolders) to find the cache files. If you have a shared Cake installation or any other fancy setup, please adjust the cache paths in the inititalize() method.
The Code
/**
* Remove Cache Shell
*
* This shell allows you to remove cache files easily and provides you with a couple configuration options.
* If run with no command line arguments, RemoveCache removes all your standard cache files (db cache, model cache, etc.)
* as well as your view caching files.
*
*
* RemoveCache Shell : Removing your Cache
* Copyright 2009, Debuggable, Ltd. (http://debuggable.com)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @filesource
* @copyright Copyright 2009, Debuggable, Ltd. (http://debuggable.com)
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
class RemoveCacheShell extends Shell {
/**
* undocumented function
*
* @return void
* @access public
*/
function initialize() {
parent::initialize();
$this->settings = array(
'view_cache_path' => APP . 'tmp' . DS . 'cache' . DS . 'views',
'std_cache_paths' => array(
APP . 'tmp',
APP . 'tmp' . DS . 'cache',
APP . 'tmp' . DS . 'models',
APP . 'tmp' . DS . 'persistent'
)
);
}
/**
* undocumented function
*
* @return void
* @access public
*/
function main() {
$args = $this->args;
$stdCache = !isset($args[0]) || $args[0];
$viewCachePattern = isset($args[1]) ? $args[1] : '.*';
if ($stdCache) {
$this->_cleanStdCache();
}
$this->_cleanViewCache($viewCachePattern);
}
/**
* Cleans the standard cache, ie all model caches, db caches, persistent caches
* Files need to be prefixed with cake_ to be removed
*
* @return void
* @access public
*/
function _cleanStdCache() {
$paths = $this->settings['std_cache_paths'];
foreach ($paths as $path) {
$folder = new Folder($path);
$contents = $folder->read();
$files = $contents[1];
foreach ($files as $file) {
if (!preg_match('/^cake_/', $file)) {
continue;
}
$this->out($path . DS . $file);
@unlink($path . DS . $file);
}
}
}
/**
* Cleans all view caching files. Takes a pattern to match files against.
*
* @param string $pattern
* @return void
* @access public
*/
function _cleanViewCache($pattern) {
$path = $this->settings['view_cache_path'];
if ($pattern{0} != '/') {
$pattern = '/' . $pattern . '/i';
}
$folder = new Folder($path);
$contents = $folder->read();
$files = $contents[1];
foreach ($files as $file) {
if (!preg_match($pattern, $file)) {
continue;
}
$this->out($path . DS . $file);
@unlink($path . DS . $file);
}
}
/**
* undocumented function
*
* @return void
* @access public
*/
function help() {
$this->out('Debuggable Ltd. Remove Cache Shell - http://debuggable.com');
$this->hr();
$this->out('Important: Configure your paths in the shell\'s initialize() function.');
$this->hr();
$this->out('This shell allows you to remove cache files easily and provides you with a couple configuration options.');
$this->out('If run with no command line arguments, RemoveCache removes all your standard cache files (db cache, model cache, etc.) ');
$this->out('as well as your view caching files.');
$this->out('');
$this->out('Set the first parameter to 0 (zero), to not remove standard cache files.');
$this->out('Set a regex pattern for the second argument, to match viewcache files to delete.');
$this->hr();
$this->out("Usage: cake remove_cache <std_cache_boolean> <pattern_to_match_viewcache_files>");
$this->out("Usage: cake remove_cache \t\t// removes all cache files");
$this->out("Usage: cake remove_cache 0 \t\t// removes only view cache files");
$this->out("Usage: cake remove_cache 0 home \t// removes only the view cache file for your homepage");
$this->out("Usage: cake remove_cache 0 articles_ \t// removes all view cache files for your articles controller");
$this->out("Usage: cake remove_cache 1 /letter_z$/ \t// removes all std cache files and view cache files ending with 'letter_z'");
$this->out('');
}
}
?>
Enjoy! Feedback welcome.
-- Tim Koschuetzki aka DarkAngelBGE
You can skip to the end and add a comment.
Tim,
Glad to see a new post! It's certainly been a while.
Any reason why you didn't use the core's clearCache function (http://api.cakephp.org/file/basics.php#function-clearCache)? I include a link to a controller action in my app's admin menu to clear the cache while logged in as admin (actually, I automatically call it at admin login as well because in production, admin always logs in immediately following an update, a time when you need the cache cleared).
I'll stay tuned!
Hah good call NOSLOW. Yeah I forgot about it in this shell - shame on me.
However, I think the shell is still slightly more flexible when it comes to custom cache paths. Remember how you can set up your cache directory in core.php?
Here is an alternative by jperras wrapped into a plugin:
For most of my projects, I have created a class made up entirely of constants that are the root to my keys. For example:
const PRODUCT_ = 'product_'; // + id
This provides a nice reference to the types of keys I have, and a programmatic way of getting to them. You can group them in arrays, then iterate through them to build out various interfaces for examining their contents, clearing groups, or adding the id to clear single keys.
I did something similar awhile back for our application. We use a shared cake and app directory, and each site we create on the server has it's on tmp and webroot directory. Each site will have different cache files so we couldn't globalize this.
To delete the cache on the entire server I use the following:
----
find / -type f \( -iname "cake_model_*" -or -iname "cake_*" ! -iname "cake_core_*" \) -user 99 >/home/cake_cache.txt
cat /home/cake_cache.txt | while read line
do
rm -f $line
done
----
Worked out pretty good so far. I'm sure there is a way to simplify this though.
This post is too old. We do not allow comments here anymore in order to fight spam. If you have real feedback or questions for the post, please contact us.
Hey there Tim,
Not that this could work on windows or anything, but the following should tackle dealing with both "argument list too long" and non-unix characters (print0 will delimit files with the 0 character, so you won't have to escape spaces or any other 'crazy' chars):
find YOUR/WEB/DIR/app/tmp/cache/ -type f -print0 | xargs -r -0 rm
It's actually a simplified version from what PHP uses to clean up session garbage files (see /etc/cron.d/php5)
If anyone has PHP on Windows they should probably be able to figure out the Windows equivalent for this cleanup command.
Just FYI. I do not intend this to replace the RemoveCache Shell or anything.