BzZzZ - ustvarjamo podobe logo
slovenščina
english
Joomla 1.6. cache changes for extension developers (Jennifer series 2)

Sorry Jennifer/Joe, I was joking, this one is really not for you.

This article is a historical sequel to Using caching in Joomla extensions that was written for Joomla 1.5. I will try to merge and expand this in the third article - but for now here are most important cache changes in Joomla 1.6. that affect Joomla extensions developers. Also reading part one of this series is advisable .

 

CHANGE OF TERMINOLOGY

In 1.5. we had 2 kinds of handlers - low level cache handlers like file cache, APC etc and higher level handlers like view cache or callback cache. In 1.6. higher level was renamed to cache controllers to better reflect it's role. Cache controllers use cache handlers to do it's work, so it is similar to controller-model relationship in MVC. The following chart can help you understand how cache library works internally:

 

 

changed COMPONENT VIEW CACHE

View display method that fires component view cache now takes an array of url parameters and their types to create Cacheid. This is a replacement for a previous unsafe way which took the whole URL and so opened the doors for DOS attacks via random parameters/values added to request (see Why URL as a cache id is inherently dangerous for more info). Although old cacheid created from URL was retained for backwards compatibility if there are no $safeurlparams, this is unsafe and is to be removed in 1.7 (if any of PLT's will get it at the time..).

An array is a simple list of url parameters and their filter types used by your component - anything else is discarded.

 

Com_contact controller usage example:

$safeurlparams = array('id'=>'INT', 'catid'=>'INT', 'limit'=>'INT', 'limitstart'=>'INT', 'filter_order'=>'CMD', 'filter_order_Dir'=>'CMD', 'lang'=>'CMD')

parent::display($cachable,$safeurlparams);

What if I have a plugin that appends url parameters to those used by the component?

In that case you must register those parameters zip via system plugin - download an example here. 

 

new progressive CACHE layer

First of all - whatever you do inside a module is covered by progressive cache mode layer above. For 99% of modules this works ok, but it might fail for some that require more changes that "one cache unit per module set" which typically is a page.

Modules with random content (e.g. random image) would be an example of this - if what you want is randomness on each page load you must use conservative cache level. Normally randomness for each different page is good enough as users don't reload the same page over and over again to se whether that module is really random.

 

 

new MODULE CACHE

Beside progressive cache, biggest changes were implemented in the area of module caching. In 1.5. you had only one modulecache mode and cache unit was defined by module id and user aid.

In 1.6. there are 5 different module cache modes of operation, 3 of them are meant to be set from module XML file, while 2 are meant to be used from within the module itself. This distinction is only a guidance, technically all 5 can be used in both ways, although they might now work as intended in that case. Default is backwards compatible oldstatic mode that requires no changes to a module.

 

MODES TO BE SET IN module XML

  • Static - one cache file for all pages with the same module parameters. Recommended for modules that don't change.
  • Oldstatic - 1.5. definition of module caching, default for backwards compatibility
  • Itemid - changes on itemid change. Suitable for most dynamic modules that change per page - like menus, content images etc

 

How is it implemented?
In addition to cache field that was required in 1.5 there is now new hidden field in module xml called cachemode and that sets any of the above modes:

<field name="cachemode"
type="hidden"
default="itemid">
<option value="itemid"></option>
</field>

 

MODES TO BE CALLED FROM INSIDE THE MODULE

  • Safeuri - Id is created from URL params array, the same as in component view cache. Use this mode if you module depends on url parameters other than Itemid to display content (e.g. module that display different image for each content category). Modeparams property is an array of url parameters and their filter types (see example bellow).
  • Id - module sets own cache id's according to it's own formula. Most flexible, but not needed often. Modeparams property is calculated id.

This modes are actually a shortcut to cache callback to avoid code duplication in every module.

 

To use this modes rename 'cache' field in xml to 'owncache' field and call JModuleHelper::ModuleCache from within the module's main php file.

<field>
name="owncache"
type="list"
default="1"
label="COM_MODULES_FIELD_CACHING_LABEL"
description="COM_MODULES_FIELD_CACHING_DESC">
<option value="1">JGLOBAL_USE_GLOBAL</option>
<option value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option>
</field>


Object properties that we need to pass to ModuleCache method are self explanatory and can be seen from this example from related items module that uses safeuri mode and replaces uncached function modRelatedItemsHelper::getList($params) :

$cacheparams = new stdClass;
$cacheparams->modeparams = array('id'=>'int','Itemid'=>'int');
$cacheparams->methodparams = $params;
$cacheparams->method = 'getList';
$cacheparams->class = 'modRelatedItemsHelper';
$cacheparams->cachemode = 'safeuri';

$list = JModuleHelper::ModuleCache ($module, $params, $cacheparams);

 


RAW CACHe

In 1.5. developers were using output cache for that purpose as that controller is missing get & store methods and that way they were able to access low level get/store from cache handlers. Things changed in 1.6. as any get/store needs to be coupled by lock&unlock operations. To make things easier an option to use raw cache was added.

Raw cache get and store are easily performed by passing '' (empty string) as cache controller to JFactory::getCache($group,$handler,$storage)

Locking & unlocking are performed automatically. One important difference to mentioned 1.5. output cache usage: data is auto serialized / deserialized (avoid double serialization or deserialization will fail).

 

 

WORKAROUNDS IN ALL CACHE TYPES (except raw)

In addition to above changes workarounds to come around known cache limitations are now much more sophisticated and since adding stylesheets or javasript via method calls from within a module or component should now be working properly.

Some cache controllers (view, callback..) now take additional parameters that turn on or off each particular workaround. This options need to used only if your cached callback function manipulates headers or pathway - options are the same as in new getWorkarounds and setWorkarounds JCache methods.

 

setWorkarounds

JCache::setWorkarounds($data,$options=array()) prepares data to be stored in cache in a workarounded way and takes the following options:

  • nopathway - do not store pathway data
  • nohead - do not store header data
  • nomodules - do not store modules data
  • modulemode - if nohead is 0, do not store the following header data: title, description, link, metaTags

 

getWorkarounds

JCache::getWorkarounds($data,$options=array()) performs workaround on stored workarounded data. It recreates header, pathway and modules and returns basic data that was stored. It works automatically - particular workaround is performed only if data for it was stored separately. It takes only one option mergehead which tells it whether to merge stored header data with the one already in buffer (default) or replace it with stored header. When merging it uses new JDocument mergeHeadData method.

 

 

SOME NOTES ON CALLBACK/FUNCTION, OUTPUT and RAW CACHE USAGE

When coding own components ready-made view cache is often not refined enough and should really be used only for simplest components. Any component that creates content on the fly should probably be using other types of cache and this is where callback and raw cache come handy.

Callback cache returns exactly the same result as non-cached function would return only that result is cached and so only first time function get actually executed.

We invoke caching by using JFactory::getCache and if we are using callback cache our code would look like this:

$cache = JFactory::getCache('somegroup', 'callback');
$result = $cache->get(array('someclass', 'somemethod'), $methodparams, $id, $workarounds, $workaroundoptions);

(last 3 parameters in italics are optional)

 

Note that this get is not the same get as when we are using raw cache. Callback cache get automatically retrieves cached data if it exists, if it doesn't, it performs callback call, returns data from callback and stores data for the next call. There is no cache callback store method!

 

By using raw cache coder has direct access to get and store methods and is responsible for necessary logic. Raw cache comes handy when we we need to store information other than function calls (e.g. xml data, images, product descriptions..) or we need to pass large amount of data from one page to another.

Code snippet for it's usage:

$cache = JFactory::getCache('somegroup', '');

if (!$somevariable = $cache->get('someCacheId')) {
// do you stuff here and put result in $somevariable
$cache->store($somevariable, 'someCacheId');
}

 

CHANGE IN JCache PARAMETERs USAGE

When using JCache classes we don't need to pass it any parameters if we are happy with the defaults, which now properly set and inherit values from configuration settings (caching true/false, lifetime, handler..).

 

FURTHER DEVELOPMENT, BUG AND SUGGESTIONS

Caching changes in 1.6. are entirely a result of my personal investment of time and knowledge (99% of code was done by me). As PLT has decided to ban me from mailing lists please address any questions you migh have to klas dot berlic at gmail dot com

 
  • strateško usmerjeno
  • integrirano
  • s kreativnostjo pospešeno
  • učinkovito komuniciranje
© BzZzZ 2008
stik z nami    zaposlitev    kazalo strani