This tutorial will review one of Platform’s most powerful features, Partial Page Caching. Partial Page Caching is used in cases where it is impractical or impossible to cache the entire output such as when sections of the script are fully dynamic or when the conditions for caching the script are too numerous. An example of this type of usage is when some of the output is a form, that has credit card numbers, addresses and all kinds of information that for security reasons, should not be cached
The following tutorial is a step-by-step guide to mastering Partial Page Caching.
Inside this tutorial, you will find several ways to cache you output:
Partial Page Caching APIs - a general overview of the Caching APIs with usage examples.
Action Based Partial Page Caching - Cache using buttons and conditions
Partial Page Caching can also be achieved using the following functions for almost all situations:
Output Caching Functions
|
Function |
Action |
|
output_cache_fetch() |
Gets the code's return value from the cache, if it is there.
|
|
output_cache_output() |
Calls a function and checks if the function exists in the cache. Yes - Print No - Puts function output in cache and prints.
|
|
output_cache_exists() |
Checks if the key exists in the cache. Yes - Print, No - Runs code, output in cache and prints until it reaches the stop command: output_cache_stop().
|
|
output_cache_stop() |
Indicates the end of a block of code. |
Data Caching Functions
|
Function |
Action |
|
output_cache_put() |
Enters a single variable into the cache |
|
output_cache_get() |
Gets the Variable from the cache at the end of its lifetime. |
Invalidate Cache
|
Function |
Action |
|
output_cache_remove_key (string key) |
Respectively remove items from the cache according to their type (Key, URL or File) |
The partial caching functions are divided into two groups, output caching and data caching. This document will explain each of the two groups and give practical examples of each function call.
The first groups of functions are the output caching functions. These functions capture the output from a function or block of PHP code and cache it. These functions are:
output_cache_output()
output_cache_exists()
output_cache_stop()
Output caching functions allow programmers to remove the execution of blocks of code with static output, such as looping over and printing the day’s news headlines. This output changes infrequently, so instead of reprocessing it for every user caching allows PHP to skip execution and print the results.
Prototype:
void output_cache_output(string key, string code, int lifetime)
The first time output_cache_output() is called, it will execute the function defined in argument two, and store any output in the cache under the retrieval key specified in argument one. Each subsequent call to output_cache_output () with the same value as argument one will result in the output of this cached data instead of the execution of the function in argument two, until the cache lifetime in argument three expires.
output_cache_output () is typically used to capture the output created by a function call. In order to use it, you would need to wrap a section of code as a function. When you call output_cache_output (), it will call this function and cache it's output.
output_cache_output () takes three arguments:
The key value with which this output will be cached.
The function call.
The cache lifetime in seconds.
output_cache_output() has no return value.
Usage Example
<?
function content($time) {
/* Create a function to Wrap the code that produces
the output */
print "<p>Cached Time: $time </p>";
/* The actual value of $time will be printed
only once every 30 seconds. The output from
the print statement will be cached, and the
function call will be ignored until the cache
lifetime expires */
}
$time = time();
/* Get current time, in seconds */
print "<p>Current Time: $time </p>";
/* Print the real current time */
output_cache_output("Current Time","content($time);",30);
/* Cache all output for the function content() and
store it based on the key "Current Time" for 30
seconds */
?>
Usage Notes:
output_cache_output() is used to cache the output generated from functions. To utilize it, wrap a section of code (which generates the output you wish to cache) as a function. Any output statements in this new function will be captured into a buffer and stored as cached data with the key specified.
The other two functions, output_cache_exists () and output_cache_stop (), are used in tandem to simplify the task of caching output from a given section of code.
Prototype:
boolean output_cache_exists(string key, int lifetime)
void output_cache_stop()
output_cache_exists() is called from a conditional statement. The conditional statement should wrap the section of code producing the output you are intending to cache.
output_cache_exists() takes two arguments:
The key value with which this output will be cached.
The cache lifetime in seconds.
output_cache_exists() returns a boolean. TRUE is the key exists, FALSE if it doesn't.
output_cache_stop() takes no arguments.
output_cache_stop() has no return value.
Usage Example
<?
if (!output_cache_exists("Some_Key2", 3)) {
echo time();
output_cache_stop(); // Stop buffering...
}
?>
In cases where caching the output from a script isn't possible, we offer a set of functions for caching data. These functions are output_cache_fetch(), output_cache_put() and output_cache_get().
Data caching allows programmers to skip execution of repetitive database calls, increasing script performance and reducing overhead on the database. Typical uses of data caching include caching user preferences, caching product pricing, or any SQL call which changes infrequently.
Prototype:
string output_cache_fetch(string key, string code, int lifetime)
output_cache_fetch() works in a similar manner to the output caching function, output_cache_output(). The major difference is that instead of caching the output from the function it caches the return value as a string.
output_cache_fetch() receives 3 arguments:
Unique identifier string for the data (string)
PHP code to be cached (string)
Cache lifetime in seconds (integer)
output_cache_fetch() returns a string containing the return value of the cached code section as defined in argument 2. The ID, defined in argument 1, serves to differentiate the code section and give it a name. Lifetime, defined in argument 3, is handled in the same way the Performance module handles cache lifetimes for all cached files -- cached copies older than the lifetime will be refreshed when the function is called.
Note:
Unlike normal caching only the return value of the given PHP code is cached.
Usage Example
<?
function get_content($time, $sec, $usec) {
/* I define an arbitrary function which
returns data. */
$data = array();
$data["time"] = $time;
$data["sec"] = $sec;
$data["usec"] = $usec;
/* Create an array to store the data.
This is where you would generate the data
you wish to cache, such as making database
calls. */
$ser_data = serialize($data);
/* serialize the array for return */
return ($ser_data);
}
$time = time(); /* get current timestamp */
$micro = microtime();
/* get current timestamp
including microseconds */
list ($usec, $sec) = explode(" ", $micro);
/* Print the real current time */
print "<p>Current Time: $time, $sec, $usec</p>";
$cached_string = output_cache_fetch("Example: Fetch","get_content($time, $sec, $usec);",30);
/* Call the function via the 'output_cache_fetch()'.
If the content key exists and the lifetime hasn't
expired, the function execution will be skipped
and the cached data will be returned via the cache
API call. */
$data = unserialize ($cached_string);
/* unserialize the data */
/* Print the cached time */
print "<p>Cached Time: " . $data["time"] . "," . $data["sec"]. "," .$data["usec"] . "</p>";
print "<p><b>Refresh to see caching in action!</b></p>";
?>
The strength of output_cache_fetch is that it allows the developer to offload repetitious database calls by wrapping these calls in a function. The following example illustrates how this would work.
<?php
/* Note that this code is kept as simple as possible,
with no return type checks etc., in order to focus
on the caching features. */
/* Display greetings and read user info from database -
this part must remain dynamic */
$user_id=($_SESSION['user_id']);
$result = mysql_query("SELECT name,country,airport
FROM users
WHERE id=$user_id");
list($name,$country_id)=mysql_fetch_array($result,MYSQL_ASSOC);
echo "<P>Welcome $name ".date("F j, Y, g:i a") ."</P> ";
/* Note that the code to be cached should be wrapped as
a single function call (see argument 2 in above
example) - this is to improve readability and code
reuse (the code we want to cache is usually longer
than one line.) */
// Display list of destination countries
$sql = "SELECT id,name FROM countries";
echo "<P>Destinations: ";
$destination_str=output_cache_fetch("destinations","GetQuery('$sql')",3600);
$destination_arr = unserialize($destination_str);
$out = "<P>Destination Airport: <SELECT NAME=\"destination_airport\">";
foreach ($destination_arr as $destination) {
$out .= "<OPTION VALUE=\""
.$destination['id']."\">"
.$destination['name']."</OPTION> ";
}
$out .= "</SELECT></P> ";
echo $out;
echo "</P>";
/* In the first caching example (above), we cache the
list of destinations. This is the same for every
user, and so the cache id is a simple string. In
the second example (below), the list of airports
depends on the user's country. So, the country_id
is added in the ID string. This will create a
different cache copy for each continent. */
// Display list of airports in the user's home country
$sql = "SELECT id,name FROM airports WHERE country='$country_id'";
$airports_str = output_cache_fetch("airports_$country_id","GetQuery('$sql')",3600);
$airports_arr = unserialize($airports_str);
$out = "<P>Departing Airport: <SELECT NAME=\"depart_airport\"> ";
foreach ($airports_arr as $airport) {
$out .= "<OPTION VALUE=\"".$airport['id']."\">".$airport['name']."</OPTION> ";
}
$out .= "</SELECT></P> ";
echo $out;
/* This function is more general purpose, meant to be
used with output_cache_fetch () it performs an SQL
query and returns the results as a serialized string.*/
function GetQuery ($sql_query) {
$result = mysql_query($sql_query);
$res_arr = mysql_fetch_array($result, MYSQL_ASSOC));
$res_str = serialize($res_arr);
return $res_str;
}
?>
Usage Notes:
You can use output_cache_fetch() to cache non-string types (e.g. arrays and objects) of PHP variables by using PHP's serialize() and un-serialize() to convert them to strings and vice versa.
output_cache_fetch requires the code which generates the cache data to be wrapped in a function. This allows the cache routine to skip the execution of this code if the data is already cached
output_cache_put() and output_cache_get() provide a direct way to store and retrieve data from the cache.
Prototype:
void output_cache_put(string key, mixed data)
void output_cache_get(string key, int lifetime)
output_cache_put() takes two arguments:
The key value with which this data will be cached.
The data to be cached. (scalar, string, or serialized data).
output_cache_put() has no return value.
output_cache_get() takes two arguments:
The key value with which the data is stored.
The lifetime that this data should be considered valid.
output_cache_put() returns the cached data, if it exists and is valid. Otherwise it returns false.
Usage Example
<?
if(($result = output_cache_get("TestFunctionResult", 30)) === false) {
$result = microtime(); /* Current timestamp */
print "<br><i>Fetching Fresh Content</i><br>";
/* Should only print this every 30 seconds when
the content is fetched fresh */
output_cache_put("TestFunctionResult", "Cached: $result");
}
print "<b>$result</b><br>";
?>
Usage Notes:
The put/get routines are a simpler method for caching data than output_cache_fetch. They are typically used for the storage and retrieval of small bits of data.
Action Based Partial Page Caching pertains to caching part of an output based on the occurrence of an action. This type of Caching is necessary in instances where it is preferable to refresh the Cache when an action occurs rather than time based.
For example: If we have a list of people who are "Currently Online" and we were to use time based caching, we would have to set an extremely short time limit to make sure that the list is updated at all times. We would also waste valuable system resources every time we refresh the cache. Instead, we can adopt a more efficient approach: refreshing the cache based on an action, for instance, every time a member goes online or logs out.
How do we do this?
There are two "Partial Page Cache" options based on an action:
Conditional Partial Page Caching
Button Based Partial Page Caching
With this option, we predetermine conditions for caching and invalidating (If X occurs then do Y).
For example: we can cache our list of people who are "Currently Online" based on their log-on action. Whenever someone logs-on, their name will be added to the cache. Subsequently, when the same person logs-off we could set another condition will remove the name from the cache.
The following code example demonstrates how to empty the cache when a certain action occurs:
if (check_some_condition()) {
output_cache_remove_key (...);
}
With this option, we set a specific button to initiate refreshing the Cache (Pressing button X does Y).
For example: we can cache our list of people who are "Currently Online" based on a specific button that the person logging-in will press (such as: login, next, go, etc). Whenever someone presses the button, his or her name will be added to the cache. Subsequently, when the same person presses a different button, his or her name will be removed from the cache.
The following example demonstrates the button triggered Partial Page Caching technique:
<form action="clean_cache.php">
<input type="submit" value="Clear Cache">
</form>
The 'action' attribute points to the clean_cache.php script. Therefore, when the user submits the form, clean_cache.php is executed+.
The clean_cache.php clears the cache (with output_cache_remove()) and then builds it again with fopen("http://..") to get a real cache refresh.
|
This tutorial detailed Action Based Partial Page Caching, with conditional or button-oriented options. |