15

Sometime I will implement changes locally and they work fine, I copy them to my remote webserver and the changed are ignored. (The code is identical.)

I go into core.php, change debugging to 3, check again... it works!

I have a feeling it's something to do with cache but I don't know what exactly to change.

1

6 Answers 6

31

CakePHP has a cache located in /app/tmp/cache. The directory structure looks like this:

# /app/tmp/cache
# /app/tmp/cache/models
# /app/tmp/cache/persistent
# /app/tmp/cache/views

The main issue usually experienced is with the model cache. When debug is off (ie. in production) and you cause CakePHP to dispatch, it introspects the schema of all your database tables and stores these in flat files in the models folder above. If you do not delete the files in this folder, CakePHP will start to say models/tables/fields don't exist when they clearly do in your database.

If you enable view caching in your application, when views are rendered for the first time CakePHP will compile flat files to the views folder to prevent having to render these views again on the next request.

During CakePHP's bootstrap process it has to determine the directory structure you are using in your installation before it can access important files (like database.php). As such, CakePHP will generate cache files to the persistent directory with the absolute paths to each and every important directory and file, any plugins you are using and even any localisations you have created so it can quickly translate your application between languages without reparsing .pot files.

So, simply put, you have to remember to delete all of the files in these directories whenever you make code changes to an application that is in production, or add this as part of your deployment mechanism. You must not delete any of the directories however.

The reason changing debug to 3 works for you is because when debug mode is turned on (at any value greater zero) the cache is cleared and regenerated on every request, but - while this works - it is not easy to automate.

There are a number of ways to do this programmatically - including shell commands, CakePHP plugins, Capistrano configs, Ant files - but one can also just do so manually.

1
  • 2
    yeah, setting Configure::write('Cache.disable', true); is useful to don't have cache. Commented Mar 26, 2014 at 15:19
6

You might find this useful for clearing cache in CakePHP 1.2, 1.3 and I think this would work in 2.x (with a little modification to make use of the new CakeRequest class):

    if(Configure::read('debug') > 0 and isset($this->params['url']['emptycache'])) {
        // clear Cache::write() items
        Cache::clear();
        // clear core cache
        $cachePaths = array('views', 'persistent', 'models');
        foreach($cachePaths as $config) {
            clearCache(null, $config);
        }
        $this->Session->setFlash('Cache cleared', 'default', array(), 'info');
    }

Add this into your AppController::beforeFilter().

Basically while you're in development mode, the above code lets you easily clear your cache by appending a query string to the URL e.g. mydomain.com/?emptycache - it will remove all of Cake's cached files.

1
  • 1
    Hmm, I'm running into an issue where I modify a table then move data all in one call (run from shell) and clearCache(null, 'models'); doesn't seem to be working (Cake is stripping the new column before it sends the query to mysql). The fix will probably be to split this into 2 calls from the shell so on the second run the cache is updated. (Cake 1.3) Commented Feb 10, 2015 at 22:07
2

It's definitely caching. On the server side if you have caching enabled, do not wonder if caching happens. You can turn this off in core.php, or more likely clear the cache Cache::clear() when you upgrade your app. On the client side you might want to tweak your browser to disable caching fully.

2
  • Wherever you want. You could have a special, restricted controller action that clears all the server-side cache. You only have to visit its url after an upgrade.
    – sibidiba
    Commented Jun 24, 2010 at 18:49
  • Tweaking the browser won't affect the server-side cache, surely?
    – Leo
    Commented Jun 25, 2010 at 8:20
1

I think it is a client-side problem. Do you have the Web Developer addon for Firefox Mozilla installed? if yes, you can easily deactivate the cache on client side just to check.

It works again if you change the debugging level because then the urls and cookie data is probably slightly different leading to a fresh reload from server. If it still does not work then it must be the server side cache...

NOTE: Beside this you can do all kind of useful things for web development with that addon like modifying css on the fly or visualizing styles as overlay on the page.

1
  • Thanks for the Web Developer addon tip. I thought I had disabled cache by putting Cache::config('default', array('engine' => 'File','duration'=>0)); in core.php - I guess I'm doing that wrong?
    – Owen
    Commented Jun 24, 2010 at 17:30
1

I had the same problem, and deizel, gave a great explanatinon, just wanted to add, if you do not make a lot of changes, the easy way, without removing or deleting the cache data, or smth like that, is to change debug level from 0 to 3, refresh the page(s), that you make changes on po file, and again set debug to 0.

1

I have found wonderful solution here. I think it should be perfect and working fine. The solution like below:

function _clear_cache()
    {

        Cache::clear();
        clearCache();

        $files = array();
        $files = array_merge($files, glob(CACHE . '*')); // remove cached css
        $files = array_merge($files, glob(CACHE . 'css' . DS . '*')); // remove cached css
        $files = array_merge($files, glob(CACHE . 'js' . DS . '*'));  // remove cached js
        $files = array_merge($files, glob(CACHE . 'models' . DS . '*'));  // remove cached models
        $files = array_merge($files, glob(CACHE . 'persistent' . DS . '*'));  // remove cached persistent

        foreach ($files as $f) {
            if (is_file($f)) {
                try {
                    @unlink($f);
                } catch (Exception $ex) {
                    $files['errors'][] = $ex->getMessage();
                }
            }
        }

        if (function_exists('apc_clear_cache')):
            apc_clear_cache();
            apc_clear_cache('user');
        endif;

        return $files;

    }

Just use above function in your appcontroller and run that function where you want it will be clear all cache.

Not the answer you're looking for? Browse other questions tagged or ask your own question.