PHP Classes

File: CachedTemplate.txt

Recommend this page to a friend!
  Classes of Jesus M. Castagnetto   Generalized CachedTemplate class   CachedTemplate.txt   Download  
File: CachedTemplate.txt
Role: ???
Content type: text/plain
Description: Class documentation
Class: Generalized CachedTemplate class
General Template Caching class
Author: By
Last change:
Date: 23 years ago
Size: 33,190 bytes


Class file image Download
CachedTemplate: A generalized template caching class Document: Version: 1.4, Copyright © 2000-2001 Jesus M. Castagnetto (, License: GPL ------------------------------------------------------------------------ New: (1.4) Added support for reading into a variable the contents of a cached file, which can be used for partial caching of page contents. An example (partial_caching.php) is included to illustrate the use of the method. New: (1.3, unreleased) Added a locking mechanism to avoid race conditions while updating a cached file (1.2) Added a general way of using user's variables for writing/reading/validating cached information. Added support for external data validation. NOTE: For questions about these classes contact me at:, any e-mail related to these classes going to any of my other e-mail addresses will go unanswered. ------------------------------------------------------------------------ Table of contents * Introduction * Class TemplateAdaptor * Class CachedTemplate * History * Known Bugs * License * Download o everything o documentation * Acknowledgements Introduction Sometime ago I made an extension to CDI's FastTemplate class (the CachedFastTemplate class), with the idea of creating a file caching mechanism that saves parsed documents to avoid processing of templates each time it is called. This simple file caching would reduce the load on the PHP interpreter by several orders of magnitude if you have a complex template. Returning a pre-parsed file is always faster than parsing it anew. But, as always happens more template classes were created each one with interesting characteristics of their own. So, I decided to reuse the code and kludge together a more general way of extending those template classes by using an intermediate TemplateAdapter class, which extends the appropriate template class, and is itself extended by the CachedTemplate class. Below is an (ugly) ASCII diagram, showing the way the template adaptor and the caching class work with an original template class. +----------+ +----------+ +----------+ | original | | template | | cached | | template +----->+ adaptor +----->+ template +=====> object instance | class | | class | | class | +----------+ +-+--------+ +----------+ | +-- init() +-- getTemplatesList() +-- getParsedDoc() +-- [accessory methods] +-- [overriding methods] The Template Adaptor class must implement the methods needed by the Cached Template class: init, getTemplatesList and getParsedDoc. To do this the Template Adaptor may need to generate accessory methods or override one or more of the original methods of the parent template class. (see documentation below for more information) This package contains adapter classes and examples for 5 different template packages: * CDI's FastTemplate class * Barnabás Debrenceni's XTemplate class * Stefan Bocskai's QuickTemplate class * Herman Veluwenkamp's HTML Template class * Richard Heyes's Template class * PHPLIB's Template class Basically I picked all the templates classes from PHPClasses (as of June 2000), and included CDI's and PHPLIB's too. TOC Class TemplateAdaptor Description: An class that extends the appropriate template class, and implements the methods needed by the CachedTemplate class: init(), getTemplatesList() and getParsedDoc(). It may need to override methods from the parent class, for examples on how to do this, look at the classes in the files: class.HTMLTemplateAdaptor.php, class.RHTemplateAdaptor.php and class.XTemplateAdaptor.php. You can easily construct your own TemplateAdaptor class by using one of the included ones as a starting point. Basically, you need to know how to call the constructor (if any) of the template class being extended, how to list the names of the template files, and how to get the parsed document as a string (so you can assign that to a variable). For example, after reading the code and documentation for PHPLIB's Template class, it was simple of create an adaptor class for it based on the existing one for the FastTemplate class. Example of definition: Below is the adaptor class for FastTemplate (class.FastTemplateAdaptor.php): <?php /* * Class TemplateAdaptor (FastTemplate version) * by Jesus M. Castagnetto ( * (c) 2000. Version 1.0 * * Description: * This class extends CDI's ( FastTemplate class, * implementing methods and attributes needed for the CachedTemplate class. * * The adaptor class needs to implement the getTemplatesList() method that * returns an array with the names of the templates loaded, and the init() * method used to initialize the constructor of the parent template class * * Changes: * 2000/06/10 - Initial release. */ class TemplateAdaptor extends FastTemplate { var $TEMPLATES = array(); /* * This method is used to initialize the parent class */ function init($pathToTemplates="") { $this->FastTemplate($pathToTemplates); } /* * method to return the list of template names */ function getTemplatesList() { if (count($this->FILELIST) > 0 ) { while (list($tag, $fn) = each($this->FILELIST)) $this->TEMPLATES[] = $this->ROOT.$fn; } return $this->TEMPLATES; } /* * method to return the parsed document */ function getParsedDoc($sect="") { return $this->fetch($sect); } } // end of class definition ?> Public Methods: init Prototype: void init ([mixed $par1 [, mixed $par2, ...]]) Definition: This method is a wrapper to initialize variables and call the constructor method (if any) of the parent template class. As such is very dependent on template class being extended, so the number and type of parameters passed is not always the same. getTemplatesList Prototype: array getTemplatesList (void) Definition: This method returns an array with the names of the templates (if any) that the main template script is using. getParsedDoc Prototype: string getParsedDoc (void) Definition: This method returns a string containing the parsed template file, in a form suitable to output back to the browser or save into a file. TOC Class CachedTemplate Description: A generalized template caching class, extends the appropriate TemplateAdaptor class. In a few words, it allows the caching of the output from parsing a template into a file, so the next time the script is requested it can just send back that file and avoid the processing overhead of re-parsing the template. This class can be used also when caching blocks of content from a page (or pages), by allowing the selective reading of cached information into a variable (see: get_from_cache()). To avoid problems when several processes attempt to read or update a cached file (race condition), a locking mechanism has been implemented, which when active, is used automatically by all the reading/writing methods of the class (see: read_from_cache(), get_from_cache() and write_to_cache()) Locking explained The logic used is the following: 1. when reading a cache file o if a lock file is found, wait for $WAITLOCK microseconds and check again o if after trying $MAXWAITLOCKCYCLES times the lock is still there this may be due to an error somewhere, emit an error and return false (read_from_cache()) or the empty string (get_from_cache()) o when the lock goes away (if there was one) read the cached info 2. when writing a cache file o if there is a lock, some other instance of the same script must be updating the info, so do nothing a return There are also methods that allow to turn on/off lock file usage, which should speed things very little in general use, and which could be useful when regenerating pages using a cron job. Usage: Modified from the sample file: fasttemplate_example.php require "./class.FastTemplate.php3"; require "./class.FastTemplateAdaptor.php"; require "./class.CachedTemplate.php"; // Instantiate a CachedTemplate object with a // lifetime of maximum 6 hours $ftpl = new CachedTemplate("./mycache",6,"hours"); // Initialize the parent template class $ftpl->init("./templates"); // Define which templates will be used // this needs to be done here so the validity of the // cached file can be correctly ascertained $ftpl->define( array( 1main => "main.tpl", table => "table.tpl", row => "row.tpl" ) ); // Check if we can send the cached file if ($ftpl->valid_cache_file()) { $ftpl->read_from_cache(); $end = $ftpl->utime(); $runtime = ($end - $start) * 1000; echo "Completed in $runtime milliseconds<BR>\n"; exit; } // Otherwise process the page (...) Attributes: This class has the following attributes (member properties): $CACHEDIR Directory to save cached files, default "./cache" $CACHELENGTH Length of caching, default: 30 units $TIMEUNIT Time unit for caching, default: "day" $TIMEUNITSARR An associative array of valid time units and the corresponding factors (divisors) to use when calculating time differences, defined as: array ("sec"=>1, "min"=>60, "hour"=>3600, "day"=>86400) $USEVARS a flag variable to indicate that the cache validation, reading and writing methods will need to also use the contents of the $VARSVAL variable. Valid values: o "in_name" - appends the output of rawurlencode on the $VARSVAL variable to the names of cached and control files o "store" - store the contents of $VARSVAL into a *.vars file, and use that file for cache validation $VARSVAL If the flag $USEVARS is set, then this variable will contain the variable name and value pairs encoded as an URL query string. If the method use_get is used, this variable will contain the global variable $QUERY_STRING. $USELOCK If the flag $USELOCK is set, then a lock will be used when reading from or writing to a cache file. Default true. Use the methods set_use_lock() and unset_use_lock() to change the status of this variable. $WAITLOCK How many microseconds (default 100,000 microseconds = 100 milliseconds) to wait until trying to read from, or write to, a locked cache file. $MAXWAITLOCKCYCLES How many times to attempt reading from a locked cache file. Default is 20 times. This is used to limit the number of retries before returning an error condition. Public Methods: set_cache_dir Prototype: void set_cache_dir (string $dir) Description: Sets the directory to be used for caching parsed documents Example: // Set the caching directory to "../mycachedir" $obj = new CachedTemplate(); $obj->set_cache_dir("../mycachedir"); set_cache_length Prototype: void set_cache_length (int $length) Description: Sets the maximum length (in time units) to keep cached documents Example: // Set the caching length to 12 hours $obj->set_cache_length(12); $obj->set_time_unit("hour"); set_time_unit Prototype: void set_time_unit (string $tunit) Description: Sets the time unit to be used for calculating the lifetime of a cached document. Valid units are: "sec", "min", "hour", "day"; if and invalid unit is used, it defaults to "day". use_get Prototype: void use_get ([string $how]) Description: Calls the method use_vars to use the contents of the $QUERY_STRING global variable for cache writing, reading and validation. The default value of the the parameter is "in_name", i.e. use the $QUERY_STRING when generating a unique name for the cache file. See the examples in the files get_example1.php and get_example2.php for more information. Note: This method has to be used before the validation methods. Example: Assuming that the script mypage.php was called using the URL:, we can use the query string as part of the name of the cached file, so if we pass other values, e.g. somevar=notsimple, a cached file will be created for each instance. $tpl = new CachedTemplate(); $tpl->init(); // use the query string for generating the names of the cache files // which is the default behavior, and equivalent to using // $tpl->use_get("in_name"); $tpl->use_get(); ... In case you prefer not to append the GET query string to the name of the cached file, then you can store it for comparison purposes: ... $tpl->use_get("store"); ... use_vars Prototype: void use_vars ([mixed $vars, string $how]) Description: Sets the variable flag $USEVARS and sets the appropriate value for the $VARSVAL variable. This method accepts as a first parameter either the string "QUERY_STRING" (when using the variables passed in a GET query string), or an array of variable names and values to be used in the writing, reading and validation of the cached files. The default values for the parameters are "QUERY_STRING" and "in_name" respectively. Valid values for $how are: "in_name" (default) and "store". Note: This method has to be used before the validation methods. Example: We will want to use some important values to generate unique cache filenames: $tpl = new CachedTemplate(); $tpl->init(); $important_vars = array( "theme" => "simple", "fgcolor" => "black", "bgcolor" => "white" ); $tpl->use_vars($important_vars, "in_name"); ... If you are using PHP4, you can use the compact function to generate the array needed. In the example below, we also decide to store the variables into a *.vars file, which will be used during validation: ... // assuming $theme, $fgcolor and $bgcolor have been defined $important_vars = compact($theme, $fgcolor, $bgcolor); $tpl->use_vars($important_vars, "store"); ... write_to_cache Prototype: void write_to_cache (string $data [, string $datacheck, string $filename]) Description: Writes the parsed data to a cache file, and generates an associated control file containing a creation timestamp, the length of time to cache the information, and the unit of time used. If the second parameter is present, it will included in the control file to be used for external data validation (see: is_data_valid). If the third parameter is present, this will be the name used for the cache and control files, otherwise the method will use the filename stored in $PHP_SELF, replacing all "/" characters with "_". Example: // write parsed document to files "coolfile.parsed.cntrl" // and "coolfile.parsed.cache", using today's timestamp // as data validation parameter $data = $obj->getParsedDoc(); $obj->write_to_cache($data, time(), "coolfile.parsed"); read_from_cache Prototype: boolean read_from_cache ([string $filename]) Description: Reads the cached file from the cache directory and sends it to the standard output, returns true on success, false otherwise. If a parameter is passed, it will be used as the name for the cached file. Example: // read the current document from cache $obj->read_from_cache(); get_from_cache Prototype: string get_from_cache ([string $filename]) Description: Reads the cached file from the cache directory and returns it as a string if succesful, an empty string otherwise. If a parameter is passed, it will be used as the name for the cached file. Example: // get a cached block in this document $header = $obj->get_from_cache("header_".$PHP_SELF); is_cached Prototype: boolean is_cached (string $filename) Description: Returns true if the file $filename is cached, false otherwise. Example: if ($obj->is_cached("coolfile.parsed")) { // do something } valid_cache_file Prototype: boolean valid_cache_file ([string $filename]) Description: Returns true if it finds a valid cache file, false otherwise. If the parameter $filename is omitted, then the variable $PHP_SELF with the "/"s replaced by "_"s will be used. The algorithm to decide whether a cached file is valid is: 1. If a cached file exists (uses method is_cached) go to the next step, otherwise return false and exit method. 2. Is the variable $USEVARS set? + No - then go to the next step + Yes - then check how do we have to use it, if the value of $USEVARS is: + "in_name" - apply URL encoding to $VARSVAL and append it to the filename for the cache and control files, then go to the next step (this is done by calling the method _gen_filename) + "store" - read the stored $VARSVAL from the *.vars file and compare with the current one, return false if they are different, otherwise go to the next step 3. Get the creation timestamp, time length and time unit from the control file. If it is an invalid time unit return false, otherwise go to the next step. 4. Get the list (if any) of templates included in the document. Loop through the list and return false if any of the templates does not exist, or has been changed since the cached file was created (use the the creation timestamp obtained in the previous step), otherwise go to the next step. 5. Finally, compare the creation timestamp with the current one, and determine if the cached file content have expired (return false) or not (return true). Example: if ($obj->valid_cache_file()) { echo $obj->read_from_cache(); } else { // parse the document and save into cache } is_data_valid Prototype: boolean is_data_valid (string $datacheck[, string $type, string $filename] Description: Used to determine if the data from an external source has changed since the cache file was last created. It expects the first parameter to be either a unix timestamp or an md5 hash of the data. The second parameter should be either "timestamp" or "md5", it defaults to "timestamp". The third parameter (if present), should be the name used to generate the cached files. The idea behind using this method is, to allow for cached data regeneration when the data contained there changes in the original source, i.e. if you are pulling the body of a page from a database, and the information in the database changes, you can use the timestamp of the changed row to decide if the page needs to be reparsed. Similar approach can be done using an md5 hash of the data, which should also detect changes in it, this is for cases in which a timestamp is not feasible. Example In the following example, we extract information from a database of news articles, so we need to check if the cached information is up to date, we use the field ts which contains a MySQL timestamp, and we ask for the corresponding unix timestamp: ... $link = mysql_pconnect(); mysql_select_db("documents"); $query = "select UNIX_TIMESTAMP(ts) from news where topic='science' "; $query .= "and subtopic='compchem' order by ts DESC limit 1"; $res = mysql_query($query, $link); list($datats) = mysql_fetch_row($res); $tpl = new CachedTemplate(); if ($tpl->valid_cache_file() && $tpl->is_data_valid($datats, "timestamp")) { // cached info valid, send it to the user } else { // parse the document } ... A similar approach can be done with data coming from files, etc. See also the files datavalid_example1.php and datavalid_example2.php. set_use_lock() Prototype: void set_use_lock (void) Description: Activates the use of locking while reading/writing cache files Example: // use locking while processing cache files $obj->set_use_lock(); unset_use_lock() Prototype: void unset_use_lock (void) Description: Deactivates the use of locking while reading/writing cache files Example: // do not use locking while processing cache files $obj->unset_use_lock(); is_locked() Prototype: boolean is_locked (string 4filename) Description: Returns true if file lock exists, false otherwise Example: if ($obj->is_locked("mycachefilename")) { // then do something; } else { // proceed as always } mk_lock() Prototype: boolean mk_locked (string 4filename) Description: Creates a lock file if one does not already exists, returning true if succesful, false otherwise Example: if ($obj->mk_lock("mycachefilename")) // then we can manipulate the cache file } else { // other process is locking the cache file, we need to wait } rm_lock() Prototype: boolean rm_locked (string 4filename) Description: Removes a lock file if one already exists, returning true if succesful, false otherwise Example: // clean old lock files if ($obj->is_locked("mycachefilename")) $obj->rm_lock("mycachedfilename"); } utime Prototype: int utime (void) Description: Returns timestamp including microseconds. Shamelessly *borrowed* from CDI's FastTemplate class Example: $start = utime(); // after some code $end = utime(); echo "Processing took: ".($end - $start) * 1000." milliseconds\n"; Private Methods: _gen_var_val Prototype: _gen_var_val (array $vars) Description: Converts an associative array of $vars[name] = value into a url query string of the form: name1=val1&name2=val2&... _gen_filename Prototype: string _gen_filename (void) Description: Generates a unique filename based on the name of the file being cached. First it replaces all slashes (/) by underlines (_), and then if the $USEVARS variable is set to "in_name", appends the rawurlencode'd contents of $VARSVAL to the filename. _key_in_array Prototype: boolean _key_in_array (string $key, array $arr) Description: Returns true if the key is in the array, false otherwise. _is_valid_time_unit Prototype: boolean _is_valid_time_unit (string $timeunit) Description: Returns true if a the parameter passed is a valid time unit, false otherwise. _mktimestamp Prototype: int _mktimestamp (void) Description: Returns a timestamp in seconds. Wrapper for time(). _diff_time Prototype: int _diff_time (int $end, int $start[, string $timeunit]) Description: Returns the difference between the $end and $start timestamps, in the units indicated by $timeunit. If the third parameter is omitted, it defaults to "day". Example: // return the number of whole days between the 2 timestamps echo $obj->_diff_time($end, $start); // return the number of whole minutes between the 2 timestamps echo $obj->_diff_time($end, $start, "minute"); TOC History * 2000-06-10: Initial release of code * 2000-07-12: I finally wrote the documentation * 2000-07-16: Added support for PHPLIB's template class. Added support for use of the GET query string to generate various cached files from the same script (method use_get). Changed my e-mail in the code. Updated the documentation * 2000-07-18: Added support for external data validation (version not released) * 2000-07-30: Reorganization of the code to use a general method for filename generation (_gen_filename), modified the external data validation method, and modified the use of user variables when writing/reading/validating cache to be more general, added the methods use_vars and _gen_var_val, eliminated the internal variable $USEGET in favor of 2 new variables $USEVARS and VARSVAL. * 2000-07-31: Added an example on how to use use_vars, modified the examples of is_data_valid, some minor code cleaning and updated the documentation. Renamed the example files get_example[12].php to use_get_example[12].php. New release: version 1.2 * 2000-08-02: Found a typo that was causing errors in the read_from_cache method. Only happened in some cases when using the "in_name" option of use_get or use_vars * 2000-09-05: Fixed mispelt "$release" var in code and the 13 typos in the previous documentation * 2000-10-07: Added locking mechanism to the class (version 1.3, unreleased) * 2001-02-06: Merged (modified) contributed code from Matthieu Casanova, which allows reading from cached files into a variable. This can be used to cache blocks of content in a page (or pages). New release: version 1.4 TOC Known bugs Bugs? this code is prefect :-) If you do find a bug, contact me at the address: (indicate "CachedTemplate BUG" in the subject) TOC License (from the GPL license) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. [Go to the URL: for the full text of the GPL License] TOC Download * Get Everything The CachedTemplate class, the TemplateAdapter classes, and the examples as a .zip or a .tar.gz archive (documentation included, ZIP created using GNU infozip). Below is the list of files included in the distribution: 1. CachedTemplate.html - this document 2. class.CachedTemplate.php - the CachedTemplate class 3. Files related to CDI's Fastemplate class + class.FastTemplate.php3 - the template class + class.FastTemplateAdaptor.php - the adaptor class + fasttemplate_example.php - example + templates/main.tpl - template used in the example + templates/table.tpl - template used in the example + templates/row.tpl - template used in the example + use_get_example1.php - example using use_get ("in_name" option) + use_vars_example.php - example using use_vars ("store" option) + datavalid_example1.php - example using external data validation ("timestamp") + partial_caching.php - example using get_from_cache to show how caching of sections of a page can be implemented 4. Files related to Herman's HTML Template class + - the template class + class.HTMLTemplateAdaptor.php - the adaptor class + herman_example.php - example + herman_template.html - template used in the example 5. Files related to Stefan's QuickTemplate class + class.QuickTemplate.php3 - the template class + class.QuickTemplateAdaptor.php - the adaptor class + quicktemplate_ex.php - example + first_example.tpl - template used in the example 6. Files related to Richard's Template class + - the template class + class.RHTemplateAdaptor.php - the adaptor class + richard_example.php - example + header-template.html - template used in the example + main-template.html - template used in the example + footer-template.html - template used in the example 7. Files related to Barnabás' XTemplate class + xtpl.php - the template class + class.XTemplateAdaptor.php - the adaptor class + xtemplate_ex5.php - example + ex5.xtpl - template used in the example 8. Files related to PHPLIB's Template class + - the template class + class.PHPLIBTemplateAdaptor.php - the adaptor class + phplibtemplate_example.php - example + ptpl_box.ihtml - template used in the example + ptpl_page.ihtml - template used in the example + get_example2.php - example using use_get ("store" option) + datavalid_example2.php - example using external data validation ("md5") 9. Miscellaneous files + COPYING - the GPL license version + LICENSE - the copyright and license notice for this package + rows.dat - data used in the datavalid_example[12].php files * Get the documentation The document you are reading now in text, Postscript or PDF formats. TOC Acknowledgements Thanks to the people who sent suggestions, requests and bug reports: (email addresses mangled in HTML code, to prevent spambot harvesting) * Jackson Tsai ( - GET query string use (feature request) * DK Kim ( - typo in class.XTemplateAdaptor.php * Skirando C. Philipona ( - PHPLIB's Template support (feature request) * Brad Atkins ( - Idea/request that lead to adding the data validation methods * Toby Champion ( - for finding the mispelt "$release" var name in the class code, and for considering that 13 typos in the documentation consists sloppy typing, that will make me use ispell more often * Andreas Mock ( - for realizing that there could be a race condition when updating a cached file, which prompted the creation of the locking methods * Matthieu Casanova ( - for contributing a method to read cached files into variables, allowing for partial caching of content in pages TOC ------------------------------------------------------------------------ Last mangled on: Tue Feb 6, 2001