Why doesn't Cache::clear() clear my (view) cache? (CakePHP) - cakephp

Even though it's documented that CakePHP will automatically clear the view caches when a model is updated, it doesn't.
It is important to remember that Cake will clear a cached view if a model used in the cached view is modified. For example, if a cached view uses data from the Post model, and there has been an INSERT, UPDATE, or DELETE query made to a Post, the cache for that view is cleared, and new content is generated on the next request.
Even calling the suggested Cache::clear() method manually does nothing. How do I clear the view cache in Cake?
(As of version 1.2.2.8120. Looking at the repository commits, even .8256 should have this problem.)

Use clearCache(), possibly automatically in a model afterSave callback:
// model file:
function afterSave($created) {
clearCache();
}
(Please also document other available solutions, this is the only one I could find.)

use Cache::clearCache();, or use Cache::delete(); to delete only the exact file you no longer want.
function afterSave($created) {
parent::afterSave(false);
Cache::delete('left_menu_eng');
}

Related

Pagination with collection.fetch() in backbone.marionette

I am trying to implement pagination with backbone.marionette's
compositeView by first doing an initial fetch:
collection.fetch({reset: true})
To load additional models into the same collection,
collection.fetch({reset: false, remove: false})
is used.
I saw that on each use of fetch() with {reset: false}
muliple add events are triggered (for every model added.)
Thats fine basically, but when looking into the annotated source
of the compositeView's appendHtml function in marionette the follwing
statement is given:
buffering happens on reset events and initial renders in order to
reduce the number of inserts into the document, which are expensive.
While this is great for the initial fetch (only 1 browser reflow), every
subsequent fetch with {reset: false} could get pretty expensive
(reflow on every single model thats added). It really seems to
append() the itemView every single time - causing a reflow
(compositeView.isBuffering is false).
Is there any way to "batch" process the models and do a single insert
(same as done on the reset event)?
Does this need an overwrite in the appendHtml implementation
and implement the batch logic by myself?
(I assume you don't want to use Backbone.paginator, for some reason. If that isn't the case, use the plugin ;-D).
You could use a technique similar to the filtered collection used here: https://github.com/davidsulc/marionette-gentle-introduction/blob/master/assets/js/entities/common.js#L2 (instanciation at https://github.com/davidsulc/marionette-gentle-introduction/blob/master/assets/js/apps/contacts/list/list_controller.js#L13).
Basically: you provide a "paginated collection" to the view, and what the paginated collection does is:
initially, return a "cloned" copy of the original collection
when you fetch on the original collection, add the fetched events in "batch" to the cloned collection, which will trigger the view to refresh (because it's listening to the cloned collection, not the original)
To minimize reflows, you can try the following:
silence the events that the collection listens to ("add", etc.)
when a group of models gets added, create a new instance of a collection view with only the new models
render the new collection view (but don't show it anywhere), and manually append the newView.el to the right place in the DOM
destroy the newView
Unfortunately, once you need to start optimizing, you tend to need to handle a bunch of things by hand...

How does collection.fetch({add:true}) work?

I added a model to my collection and did model.save The data gets saved on the server.
After this I call collection.fetch({add:true}). Ideally only one model should be returned from server ie the newly added one but I'm seeing the entire collection being propagated back in chrome developers tool.
I'm confused. how does this actually work ?
As an add-on to Cyril N.'s answer (which describes essentially the default behavior, and should be enough I guess), I'd like to explain more thoroughly the role of the 3 flags:
add: whether or not Backbone should create and add to the collection the models which don't exist yet (ie, whose id are not in the collection)
remove: whether or not Backbone should remove from the collection the models which were not brought back from the server (ie, whose id were not is the brought back data)
merge: whether or not Backbone should update the models which are not in the first two categories (already in the collection, and brought back from the server)
However, I like to expand a bit further about the general behavior of the method (it uses the Collection#set method as a callback, so it's more the Collection#set's behavior). Backbone prepares the models, which means it creates fake, volatile models at the beginning of the method (they're only volatile if they're not added). This can lead to unexpected behaviors: because it creates models, the initialize method of those are executed.
Also, as a side-note, since Backbone 1.0, the Collection#reset flag was introduced if you want to reset your collection when fetching (therefore it uses this method as a callback). Before that, it was the default behavior of the Collection#fetch method.
Well, with both answers you should have every info you need I guess.
When you call collection.fetch({add:true}, Backbone will request the server with the complete list of items in the collection (hence the entire collection you see in the Chrome developers tool), but then, instead of reloading the entire collection in the Collection Object in Backbone (Javascript), Backbone will performs a "smart" update of the collection.
The set method performs a "smart" update of the collection with the
passed list of models. If a model in the list isn't yet in the
collection it will be added; if the model is already in the collection
its attributes will be merged; and if the collection contains any
models that aren't present in the list, they'll be removed. All of the
appropriate "add", "remove", and "change" events are fired as this
happens. If you'd like to customize the behavior, you can disable it
with options: {add: false}, {remove: false}, or {merge: false}.
Source: http://backbonejs.org/#Collection-set
All the smart work is made client side, in Javascript, but for that, Backbone request the entire collection from the server to compare it with what it has in local (client side).
(I hope I'm clear ;)).

CakePHP: Caching does not work

I am having the following issues: my cakephp app is not handling the cache thing properly. As suggested by every result in google, I created a function in the model to manually delete the cache:
public function afterSave($created) {
Cache::clear();
clearCache();
}
Unfortunately, this is doing nothing. Doesn't delete anything, and I still have the problem.
In case I have no explained myself properly, I will give an example of what happens:
I go with my browser to a page that shows a list of the last 5 records in my database. Then I go and add another record. I come back to the page that shows the last 5, and the information is not updated. It uses the cache and comes back with outdated info. If I press F5, then he page trully reloads and I see the trully 5 last records.
And that's it, I don't know what to do. The whole app works like crap, because you do something and it never appears unless you refresh the page with F5, which is something of course users are unaware, leading them to think "nothing was added" when it actually was.
Cache::clear() will only clear entries that have expired.
Try Cache::clear(FALSE). Works if you have CakePHP 2.x.
I did this to solve the problem: In the controllers, inside beforefilter function I made a check, if the action is something I disable the cache.
The actions you choose won't have browser cache.
function beforeFilter(){
if ($this->action == 'youraction'){
$this->disableCache();
}
}
Use of caching required lots of thinking, where to use where to not. If your update is frequent, don't use caching there.
We use caching where data rarely change, at that moment it is win-win situation.
Cache::clear($check, $config = 'default')
Destroy all cached values for a cache configuration.
cakephp Caching

extend Backbone.sync to batch sync?

What technique shall one use to implement batch insert/update for Backbone.sync?
I guess it depends on your usage scenarios, and how much you want to change the calling code. I think you have two options:
Option 1: No Change to client (calling) code
Oddly enough the annotated source for Backbone.sync gives 'batching' as a possible reason for overriding the sync method:
Use setTimeout to batch rapid-fire updates into a single request.
Instead of actually saving on sync, add the request to a queue, and only batch-save every so often. _.throttle or _.delay might help you here.
Option 2: Change client code
Alternatively, instead of calling save on your models, you could add some sort of save method to collections. You'd have to track which models were actually modified and hence in need of update, since as far as I can tell, Backbone only knows whether they're new or not (but I could be wrong about that).
Here's how I did it
Backbone.originalSync = Backbone.sync;
Backbone.sync = function (method, model, options) {
//
// code to extend sync
//
// calling original sync
Backbone.originalSync(method, model, options);
}
works fine for me , and I use it to control every ajax request coming out of any model or collection

Detecting insert/update/delete in CakePHP's AppController's afterFilter method

I have some code I've added to the afterFilter() method of my AppController (/app/app_controller.php) in a CakePHP app I'm developing. This code rebuilds a large, static file and I only want to incur the overhead of that rebuild when a record has been inserted, updated, or deleted. Apart from setting some sort of flag in every controller's actions that perform an update, is there a way to detect whether the database has been modified during a request?
In the model (app_model if you want it for every model) you may use afterSave function you may use it just when you do a save/saveAll that normally is what you use to create/uodate in cake.
Also you have the afterDelete method to do it when you delete something.
hope this helps you :)

Resources