written by Daniel Pötzinger CTO
TYPO3 Caching and the cHash
TYPO3 Caching and the cHash
March 02, 2012 | Categories: Web Development , Technologies & Open Source
About author Daniel Pötzinger Daniel Pötzinger CTO

cHash?

There is a pretty old but nice article from Kasper, that explains the purpose of cHash[1].

To summarize this: If a cHash (or cache Hash) is part of the current URL, and if that cHash is correct, TYPO3 generates a cache entry for the generated content. The cHash is only correct if TYPO3 itself generated the URL.

So with the help of the cHash TYPO3 can cache multiple variants of a page - depending on its request parameters. This is used for example to cache all the detail views of your news records.

1) Cache generated pages in TYPO3

Since the content on a page can differ depending of many things, TYPO3 Caches seperate variants based on:

  • Different usergroups
  • the different states of all typoscript conditions. (This depends on your typoscript setup)
  • Diffrent values of predefined Core parameters if they are valid (id, type, MP)
  • Based on other incoming parameters if the cHash matches. This last point is important to understand - since this is what you need to make your extension output cacheable the way you want.

2) Have dynamic content

TYPO3 has the concept to support dynamic elements on a page.
It works in a way, that the page itself is cached, but in the cache there can be Placeholders that get replaced before the content is send to the user.

This can be achieved using _INT Typoscript Objects like USER_INT or COA_INT.

Extbase supports uncached actions - but at the end it uses the same concept - since the extbase converts itself to USER_INT if an uncached action is called.

There are third party extensions that modifies the _INT behaviour - so that the dynamic elements are loaded by ajax calls on the client side. Which is a good approach and gives additional performance - if you can rely on enabled javascript.

3) Avoid uncached contend:

That is easy. Just set the disableNoCacheParameter setting in your localconf.php to 1 and the pageNotFoundOnCHashError also to 1.

cHash details

Imagine the following Use-Cases:

News Single Plugin:

You have a single view that displays some data based on a "tx_news_pi1[uid]" parameter.  
So this is straight forward: If you have a valid cHash for that parameter TYPO3 caches a separate variant of this page (e.g. id=12&tx_plugin_pi1[uid]&cHash=<correct_news_cHash> )

Search Plugin:

Its a different story for a search plugin: You have a search that searches for things based on a query: You are not allowed to have a cHash Parameter then.

You want this for two reasons: 1) You dont want to cache every search 2) The user enters the searchword - and its hard to generate the correct cHash.

Your URLs need to look like this:
id=12& tx_search_pi1[query]=test
id=12& tx_search_pi1[query]=test2

TYPO3 will then have only one Cache entry for that page. But your plugin will be a USER_INT and therefore can evaluate this parameter each time and displays the correct search.

current cHash problems and limitations

It is not possible to have this behaviours mixed on one page:  If you have elements on your page that should be cached based on some parameters but you still want to have elements that needs to be uncached. And there are many use-cases for this.

To come back to the two examples, imagine you have the search and the news plugin on one page:

Url:  id=12&tx_search_pi1[query]=test&tx_plugin_pi1[uid]=1&cHash= <correct_news_cHash>

=> will not work since the cHash is not valid anymore. (It triggers 404 - or delivers uncached page - depending on your settings)

Url: id=12& tx_search_pi1[query]=test&tx_plugin_pi1[uid]=1
Will not work since with a missing cHash TYPO3 might deliver the wrong cached content for the news extension.

Url:  id=12& tx_search_pi1[query]=test&tx_plugin_pi1[uid]=1&cHash=<the_new_correct_cHash>
If you manage to gerenate this urls, it will work but you pollute the Cache Table with new entries for every tx_search_pi1 parameter

Also the current extbase uncached actions solution is another example for the same problem. Since extbase replaces USER to USER_INT on the fly if an uncached action is called it needs to have the cHash Parameter set. Which results in a new Cache entry for every Parameter combination of your uncached action. This is not what you want.

A third aspect of that problem is, that parameters like "L" or other Parameters that might be part of some conditions are used for cHash calculation also. That can cause tricky bugs and uncached pages also. Its not required that parameters, that are evaluated in typoscript conditions require a cHash.

The solution: Flexible cHash calculation

The cHash should (and have to) be only calculated and evaluated for parameters that are used in cachable plugins (or actions).

For the above example that means:

Url: id=12&tx_search_pi1[query]=foo&tx_plugin_pi1[uid]=1&cHash=<correct_news_cHash>
and Url: id=12&tx_search_pi1[query]=bar&tx_plugin_pi1[uid]=1&cHash=<correct_news_cHash>
should both result in a cache hit.

Url: id=12&tx_search_pi1[query]=test&tx_plugin_pi1[uid]=1&cHash=wrongcHash
 should throw an error (404) since its a wrong cHash

Url: id=12&tx_search_pi1[query]=test&tx_plugin_pi1[uid]=1
should throw an error since the cHash is missing but required for tx_plugin_pi1[uid]

Thanks to all the reviewers - especially Tolleiv - the improvement made it into the Core [2] - and you now have the possibility to control which parameters should be used for cHash logic in the install tool:

cHashExcludedParameters: The the given parameters will be ignored in the cHash calculation. Example: L,tx_search_pi1[query]

cHashOnlyForParameters: If set only the given parameters will be evaluat
ed in the cHash calculation. Example: tx_news_pi1[uid]. Only use this if you are sure to know all relevant parameters.

cHashRequiredParameters: Configure Parameters that require a cHash. If no cHash is given but one of the parameters are set, then TYPO3 triggers the configured cHash Error behaviour

cHashExcludedParametersIfEmpty: Configure Parameters that are only relevant for the chash if there's an associated value available. And asterisk "*" can be used to
skip all empty parameters.