## Apache Zeta Components Manual :: Docs For Class ezcTemplateCacheManager

### Template::ezcTemplateCacheManager

### Interface ezcTemplateCacheManager

Interface for the class that implement a cache manager.

Implementing this interface gives the application using ezcTemplate the possibilities to:

- Mark cache files invalid based on certain criteria in your application.
- Remove old cache files.
- Keep track of the cache dependencies.

The user application and ezcTemplate call methods of the implemented interface. In this way the application communicates with the Template component.

The CacheManager implementation of should be made available to the Template component. Register the CacheManager implementation to the 'cacheManager' property in the TemplateConfiguration.

The next example shows how the cache manager 'MyCacheManager' is registered:

1. $config=ezcTemplateConfiguration :: getInstance ()
2. $config->cacheManager=newMyCacheManager();

The methods in this interface that are called only by ezcTemplate:

- startCaching: A new or existing cache file is going to be (over)written.
- stopCaching: The cache file is created.
- isValid: The Template component request whether the given (parameter) cache file is valid.
- includeTemplate: A sub template is included.

Remaining methods from the interface are only called by the user application:

- register: Register a value (eg. userID) that is related to the cache file currently created.
- update: A registered value is updated. This may indicate that a cache file is outdated.

A typical cache creation process is as follows:

1. The user application calls $t->process("my_template.ezt").

2. The template "my_template.ezt" uses {cache_template}. A custom function {fetch} retrieves query results from the database and returns the results in one or an array of objects. The idea behind this is that when the cache is enabled, the expensive {fetch} query will be omitted.

3. If a cache file exists for the requested template, the template component calls CacheManager::isValid() to see whether the cache file is still correct. If the cache file is still correct, it will execute it and return. Otherwise it will (over)write the cache file.

4. When the cache file needs to be recreated, it calls CacheManager::startCaching() first. The CacheManager is now informed that the operations in the user application originate from the template that is creating the cache. For example, the operations performed on the database are (indirectly) invoked, via a custom block or function, by the Template engine.

5. The application code that returns the requested data should also inform the Cache Manager via the CacheManager::register() method. For example, the Custom Function {fetch} calls CacheManager::register( "user", $userID ) for each requested user.

The CacheManager::register() method stores the values in the database and relates it to the cache file currently in creation. When one of these values changes, the cache file would be outdated.

6. The CacheManager::includeTemplate() is called when another template is included. Relate the current cache with the included template and store it (for example in the database). The CacheManager::isValid() can then also outdate the cache when a sub template is modified.

7. The CacheManager::stopCaching() is called when the cache file is created.

8. The user application should call the CacheManager::update() method when a change in the database or application may affect any of the caches.

Keeping track of the values used in the caches can probably best stored in a database. Using the file system only is also possible but makes things more complicated. The documentation of each method in this interface has also an example implementation. The examples rely on a MySQL database with at least the following tables.

The table 'cache_files' has (at least) the following properties:

1. +---------------+------------------+------+-----+---------+----------------+
2. |Field|Type|Null|Key|Default|Extra|
3. +---------------+------------------+------+-----+---------+----------------+
4. |id|int(10)unsigned|NO|PRI|NULL|auto_increment|
5. |cache|varchar(255)|NO|MUL|         |                |
6. |expired|tinyint(4)|NO|     |0|                |
7. +---------------+------------------+------+-----+---------+----------------+

- id: Is the unique cache ID
- cache: The (relative) path to the cache file.
- expired: Has the value 0 if the cache is valid, otherwise 1.

The table 'cache_values' has the following properties:

1. +-------------+------------------+------+-----+---------+-------+
2. |Field|Type|Null|Key|Default|Extra|
3. +-------------+------------------+------+-----+---------+-------+
4. |cache_id|int(10)unsigned|NO|PRI|         |       |
5. |name|varchar(50)|NO|PRI|         |       |
6. |value|varchar(255)|NO|PRI|         |       |
7. +-------------+------------------+------+-----+---------+-------+

- cache_id: The relation to 'cache_files.id'.
- name: Name of the value that is stored.
- value: The value that belongs to the name. Name, value combination is up to user application.

Another table can also store the cache keys that belong to the cache. The structure of this table is similar to the 'cache_values' table.

Source for this file: /Template/src/interfaces/cache_manager.php

Version: | //autogen//

### Method Summary

public void | `cleanExpired( )` The cleanExpired method should remove the expired caches.
public void | `includeTemplate( $template , $templatePath )` This method is called by the template engine when another template is included.
public void | `isValid( $template , $templateName , $cacheName )` The isValid method is called by ezcTemplate to verify whether the cache is valid.
public void | `register( $name , $value )` The user application should call this method to register values used in the current cache creation.
public void | `startCaching( $template , $templatePath , $cachePath , $cacheKeys )` The template engine calls this method when a new cache file will be created.
public void | `stopCaching( )` The stopCaching method is called by the Template Engine when the cache file is created.
public void | `update( $name , $value )` The user application should call this method when the value changes that is previously registered with the register() method.

### Methods

#### cleanExpired

void cleanExpired( )

The cleanExpired method should remove the expired caches.

The unused cache files on the hard-disk and the entries from the database tables: cache_values and cache_files can be removed. This method should be called once in a while to garantee that the system is not flooded with expired cache data.

An example implementation:

1. $db=ezcDbInstance :: get ();
3. $q=$db->prepare("SELECT * FROM cache_templates WHERE expired = 1");
4. $q->execute();
5. $rows=$q->fetchAll();
7. foreach($rowsas$r)
8. {
9. unlink ($r["cache"]);
10. }
12. $db-> exec ("DELETE FROM cache_values USING cache_values, cache_templates WHERE cache_templates.id = cache_values.template_id AND cache_templates.expired = 1  ");
13. $db-> exec ("DELETE FROM cache_templates WHERE cache_templates.expired = 1");

#### includeTemplate

void includeTemplate( ezcTemplate $template , string $templatePath )

This method is called by the template engine when another template is included.

The implementation of this method should register the current included template. The following code registers all the included templates and relates them to the cache file in creation.

1. if($this->depth>=0)
2. {
3. $db=ezcDbInstance :: get ();
4. $id=$this->keys[$this->depth]["cache_id"];
6. // Insert your parent template in the value table.
7. $q=$db->prepare("REPLACE INTO cache_values VALUES(:id, :name, :value)");
8. $q->bindValue(":id",$id);
9. $q->bindValue(":name","include");
10. $q->bindValue(":value",$templatePath);
11. $q->execute();
12. }

##### Parameters:

Name | Type | Description
--- | --- | ---
`$template` | ezcTemplate |
`$templatePath` | string |

#### isValid

void isValid( ezcTemplate $template , string $templateName , string $cacheName )

The isValid method is called by ezcTemplate to verify whether the cache is valid.

The steps that could be implemented:

1. Check if the current cache file is registered and if the cache file is expired. If the cache is not registered or the cache file is marked invalid, return false.

2. An extra step could be to check whether the current cache file is newer than all included templates. The included templates are the templates included during the creation of this cache file. The check ensures that the templates modified by hand also renew the affected cache files. Usually, this step should only be performed during development, because of the overhead.

The following code is an implementation of the steps above:

1. $db=ezcDbInstance :: get ();
3. // (1)
4. // Check whether the cache is registered and if it's expired.
5. $q=$db->prepare("SELECT id, expired FROM cache_files WHERE cache = :cache");
6. $q->bindValue(":cache",$cacheName);
7. $q->execute();
9. $r=$q->fetchAll();// Expect 0 or 1 result
11. if( count ($r)==0||$r[0]["expired"]==1)
12. {
13. returnfalse;
14. }
16. // (2)
17. // Go through all modification times.
18. $q=$db->prepare("SELECT * FROM cache_values WHERE name = 'include' AND cache_id = :id");
19. $q->bindValue(":id",$r[0]["id"]);
20. $q->execute();
22. $r=$q->fetchAll();
23. foreach($ras$a)
24. {
25. if( filemtime ($a["value"])>filemtime ($cacheName) )
26. {
27. returnfalse;
28. }
29. }
31. returntrue;

##### Parameters:

Name | Type | Description
--- | --- | ---
`$template` | ezcTemplate |
`$templateName` | string |
`$cacheName` | string |

#### register

void register( string $name , string $value )

The user application should call this method to register values used in the current cache creation.

Typically, the function that does a database query and returns the result set should also call the register() method. The implementation of the register method should update the 'cache_values' table for all the cache_files on the stack. See the next example code:

1. $db=ezcDbInstance :: get ();
2. for($i=0;$i<=$this->depth;$i++)
3. {
4. $s=$db->prepare("REPLACE INTO cache_values VALUES ( :id, :name, :value )");
5. $s->bindValue(":id",$this->keys[$i]["cache_id"]);
6. $s->bindValue(":name",$name);
7. $s->bindValue(":value",$value);
8. $s->execute();
9. }

The member variables: $this->depth and $this->keys keep the amount of cache files and the cache file data that currently created. Notice that the amount of cache files on the stack only increases with a 'template include' to another cache file.

In the cache_values table maps a name, value to an ID. The update() method uses this information.

##### Parameters:

Name | Type | Description
--- | --- | ---
`$name` | string |
`$value` | string |

#### startCaching

void startCaching( ezcTemplate $template , string $templatePath , string $cachePath , array(string=>string) $cacheKeys )

The template engine calls this method when a new cache file will be created.

The $template parameter contains the Template object. This allows you to reach the current template configuration, if needed. The $templatePath is the (relative) path to the template currently creating the cache file. The $cachePath is the (relative) path to the cache file.

$cacheKeys contains all cache keys used in the template (if any).

The startCaching method commonly performs the following steps, of course it's up to your application:

1. Register the cache file in the cache_file table of the database. If the cache file is available set the expired status to 0. Otherwise add the cache to the table, with a new id and expired set to 0.

2. Push the current cache information: cacheKeys, templatePath, Template object on an internal stack. Other CacheManager methods need this information.

3. Store the current template path in a database table that handles the included templates. The current template includes 'itself'. This makes it easier to mark the this cache outdated.

The following code demonstrates the steps from above and uses the ezcSignalSlot component to send the signals to the register method:

1. // Get the current database handler.
2. $db=ezcDbInstance :: get ();
4. // (1)
5. // Get the current cache ID, if it does exist.
6. $q=$db->prepare("SELECT id FROM cache_files WHERE cache = :cache");
7. $q->bindValue(":cache",$cachePath);
8. $q->execute();
10. // One result and make sure the query is terminated.
11. $r=$q->fetchAll();
13. if( sizeof ($r)>0)// Do we have any results?
14. {
15. $id=$r[0]["id"];
16. // Unexpire the cache_file.
17. $s=$db->prepare("UPDATE cache_files SET expired=0 WHERE id = :id");
18. $s->bindValue(":id",$id);
19. $s->execute();
20. }
21. else
22. {
23. // Insert the new cache file
24. $q=$db->prepare("INSERT INTO cache_files VALUES( '', :cache, '', 0)");
25. $q->bindValue(":cache",$cachePath);
26. $q->execute();
27. $id=$db->lastInsertId();
29. // (3)
30. // Insert your own template in the value table.
31. $q=$db->prepare("REPLACE INTO cache_values VALUES(:id, :name, :value)");
32. $q->bindValue(":id",$id);
33. $q->bindValue(":name","include");
34. $q->bindValue(":value",$templatePath);
35. $q->execute();
36. }
38. // (2)
39. // Depth keeps track of the amount of caches stored on the stack.
40. $this->depth++;
41. array_push ($this->keys,array("cache_path"=>$cachePath,"cache_id"=>$id));

The code above assumes that the private or protected member variables $depth and $keys are available in the class.

##### Parameters:

Name | Type | Description
--- | --- | ---
`$template` | ezcTemplate |
`$templatePath` | string |
`$cachePath` | string |
`$cacheKeys` | array(string=>string) |

#### stopCaching

void stopCaching( )

The stopCaching method is called by the Template Engine when the cache file is created.

The current cache information: cacheKeys, templatePath, Template object can be popped from the internal stack. This is demonstrated in the following code:

1. // Remove the current template cache in process.
2. $this->depth--;
3. array_pop ($this->keys);

#### update

void update( string $name , string $value )

The user application should call this method when the value changes that is previously registered with the register() method.

Any name-value combination that is registered should be updated when the value changes. The cache file(s) using this name-value are marked as expired.

The next example implementation expires all the cache files that uses the name-value:

1. $db=ezcDbInstance :: get ();
2. $qry="UPDATE cache_files, cache_values SET cache_files.expired=1 ".
3. "WHERE cache_files.id = cache_values.cache_id AND cache_values.name = :name AND cache_values.value = :value";
4. $s=$db->prepare($qry);
5. $s->bindValue(":name",$name);
6. $s->bindValue(":value",$value);
7. $s->execute();

##### Parameters:

Name | Type | Description
--- | --- | ---
`$name` | string |
`$value` | string |

Documentation generated by phpDocumentor 1.4.3