Bitrix Site Manager

Component cache

To boost client request processing and reduce server load, components ought to use caching. Generally, components should cache information that does not depend on the client. For example, the list of site news is identical to all visitors and it is senseless to call database routines every time this information is required. Caching time depends on how frequent new information arrives to the database. Sometimes visitor dependent information can also be cached.

Built-in cache

Components 2.0 offer the built-in caching support. The following example illustrates how a component can use the built-in caching.

// Verify and initialise input parameters
if ($arParams["ID"] <= 0)
   $arParams["ID"] = 10;

// Check whether valid cache exists
// if not, fetch data and create cache if ($this->StartResultCache()) { // Execute query and fill in $arResult $arResult = array( "ID" => rand(1, 100) ); for ($i = 0; $i < 5; $i++) $arResult["FIELDS"][] = rand(1, 100); // If some condition is true - // do not cache if ($arParams["ID"] < 10) $this->AbortResultCache(); // Connect display template $this->IncludeComponentTemplate(); } // Call delay function to set page title $APPLICATION->SetTitle($arResult["ID"]);
Notes

StartResultCache has the following prototype:

bool $this->StartResultCache($cacheTime = False, 
                             $additionalCacheID = False,
                             $cachePath = False)
where:

If the valid cache exists, the method displays its contents, fills in $arResult and returns False; otherwise, it returns True.

If the cache depends on some other parameters in addition to the site ID, input parameters, component name and the site path, you have to pass these parameters as a string in the second parameter. For example, if the cache depends on user groups whose member is the current user, the following code applies:

if ($this->StartResultCache(false, $USER->GetGroups()))
{
   // No valid cache. 
   // Select data from database to $arResult }

If, when creating a new cache, it turned out that the information should not be cached, call the following method:

$this->AbortResultCache();

For example, you may need to abort creating the cache if there is no news with a specified ID. If you do not abort cache, criminals can grow the cache to the maximum available disk space by calling the page with arbitrary ID's.

The method

$this->IncludeComponentTemplate();

connects the component template and stores the output and $arResult in the cache. All changes made to $arResult and the output emitted after calling this method will not be stored in cache.

If the following condition is false:

if ($this->StartResultCache())

it means that there is a valid cache for the given component, page and input parameters. Calling this method displays cached HTML and fills in $arResult. Now we can perform some required actions, e.g. set the page title using delay functions.

The following method allows to clear the cache if required (e.g. upon data change):

$this->ClearResultCache($additionalCacheID = False, 
                        $cachePath = False)

Parameters of this method are identical to those of StartResultCache.

Complex caching

If your component requires special caching algorithm that cannot be implemented using the built-in functions, you can use the CPHPCache class. A sample caching solution could be the following:

// Verify and initialise input parameters
if ($arParams["ID"] <= 0) $arParams["ID"] = 10; $arParams["CACHE_TIME"] = IntVal($arParams["CACHE_TIME"]); $CACHE_ID = SITE_ID."|".$APPLICATION->GetCurPage()."|"; // Cache depends only on preprocessed parameters (without "~") foreach ($this->arParams as $k => $v) if (strncmp("~", $k, 1)) $CACHE_ID .= ",".$k."=".$v; $CACHE_ID .= "|".$USER->GetGroups(); $cache = new CPageCache; if ($cache->StartDataCache($arParams["CACHE_TIME"], $CACHE_ID, "/".SITE_ID.$this->GetRelativePath())) { // Query data and build $arResult $arResult = array("a" => 1, "b" => 2); // Connect temlpate $this->IncludeComponentTemplate(); $templateCachedData = $this->GetTemplateCachedData(); $cache->EndDataCache( array( "arResult" => $arResult,       "templateCachedData" => $templateCachedData ) ); } else { extract($cache->GetVars()); $this->SetTemplateCachedData($templateCachedData); }
Notes

The cache should depend only on prepared and verified (properly initialised and type cast using IntVal etc.). $arParams contain both prepared and original parameters (prefixed with "~"). If the cache depends on unprepared parameters, hackers get a chance to grow the cache up to the top by calling the page with the ID of "8a", "8b", ... (whose IntVal() is 8).

The method

$this->IncludeComponentTemplate()

does not sends queries to the database. However, you should also call it since it performs some disk operations.

Before calling the caching completion method (EndDataCache), you have to call the template and obtain parameters that should be used even if the cache is valid. In the current implementation, such parameters are CSS styles that are attached by delay functions and do not get into cache. The structure of data returned by template is not documented; it is meaningless to component. It is just data that is to be put into cache, obtained from cache and returned to a template.

To bring data stored in cache (upon the template request) back to a template, call

$this->SetTemplateCachedData($templateCachedData);

This method should be called in the block that is executed if there is a valid cache. When calling the method, pass the template data to it.