Simple Php Cache System
Jun 2nd, 2008 | By admin | Category: Featured, PhpOverload Problem
Server overloads are one of the headaches of webmasters, especially if a popular web site is what we are talking about. It is usually because of lots of queries sent by users to servers. Server can be overloaded with those queries and as a result, responses by server can be very slow.
One thing about this repeated user queries to php servers is that it’s usually same or similar. Think we have a news blog about economy, and it is updated weekly. Queries to index page is same whole week and the response is exactly same. It’s news. With every query, server responses the latest news. So why do we query our php server again again, if we know the response already. Why don’t we save server’s response as html and send it to user. After next query, we send the saved html file to user, instead of quering and compiling php page.
Solution: PHP Caching:
Given a time interval, php’s response can be saved into a directory named /cache/ with time information added. Our cache system, checks if there is a saved response of php file in given time interval when a new user sends a query to php page. If there is, no need to compile and translate php page again, our cache system sends the saved copy of the page (cache) to user. If our cached page is old enough, system saves the response of php page again for next queries.
So how do we do that?
First we create a directory named, cache to save all our cached pages. If you have a linux server, change it permissions to 755 which will give write permission to our cache system.
The next step is to form our cache system’s php code. First, create a php file, named cache.php.
In cache php, we will have two main functions, first will cache our php files and save it into /cache/ folder. Second function, is to display the cached page if there is one.
Caching Function
function getUrl () { if (!isset($_SERVER['REQUEST_URI'])) { $url = $_SERVER['REQUEST_URI']; } else { $url = $_SERVER['SCRIPT_NAME']; $url .= (!empty($_SERVER['QUERY_STRING']))? '?' . $_SERVER[ 'QUERY_STRING' ] : ''; } return $url; } //getUrl gets the queried page with query string function cache ($buffer) { //page's content is $buffer $url = getUrl(); $filename = md5($url) . '.cache'; $data = time() . '¦' . $buffer; $filew = fopen("cache/" . $filename, 'w'); fwrite($filew, $data); fclose($filew); return $buffer; } |
getUrl function, is defined to get the queried url. This URL will be encrypted and be the name of cached page in cache folder. Cache function, calls the getUrl function to assign the web page’s address to $url. After encrypting it using md5 algorithm, time is added in front of the content. Then all the data (time and content) is saved into cache/, also returning the content to output.
Outputting Cache Function
function display () { $url = getUrl(); $filename = md5($url) . '.cache'; if (!file_exists("cache/" . $filename)) { return false; } $filer = fopen("cache/" . $filename, 'r'); $data = fread($filer, filesize("cache/" . $filename)); fclose($filer); $content = explode('¦', $data, 2); if (count($content)!= 2 OR!is_numeric($content['0'])) { return false; } if (time()-(100) > $content['0']) { // 100 is the cache time!!! return false; } echo $content['1']; die(); } |
In the above code, again the url is encrypted using md5 since all the cache files’ names in cache directory are encrypted as well. Then, cache file is checked if it is in cache directory, if not function returns false. After confirming cache file’s existance, the time in cache file is checked whether cache is new enough to output. If yes, its content is returned.
Combining Cache and Display Functions
function getUrl () { if (!isset($_SERVER['REQUEST_URI'])) { $url = $_SERVER['REQUEST_URI']; } else { $url = $_SERVER['SCRIPT_NAME']; $url .= (!empty($_SERVER['QUERY_STRING']))? '?' . $_SERVER[ 'QUERY_STRING' ] : ''; } return $url; } //getUrl gets the queried page with query string function cache ($buffer) { //page's content is $buffer $url = getUrl(); $filename = md5($url) . '.cache'; $data = time() . '¦' . $buffer; $filew = fopen("cache/" . $filename, 'w'); fwrite($filew, $data); fclose($filew); return $buffer; } function display () { $url = getUrl(); $filename = md5($url) . '.cache'; if (!file_exists(cache_dir . $filename)) { return false; } $filer = fopen("cache/" . $filename, 'r'); $data = fread($filer, filesize("cache/" . $filename)); fclose($filer); $content = explode('¦', $data, 2); if (count($content)!= 2 OR !is_numeric($content['0'])) { return false; } if (time()-(100) > $content['0']) { // 100 is the cache time here!!! return false; } echo $content['1']; die(); } // Display cache (if any) display(); // if it is displayed, die function will end the program here. // if no cache, callback cache ob_start ('cache'); |
Display function is called after defined, it checks if an appropriate cache file exists, if yes, it outputs its content and end the program, if not, cache function is called with ob_start function to store the cache in cache directory.
nice code!
its more efficient and orderly to run a cron to write your cache (rather than rely on the next visitor). even if u are the ‘next’ visitor, hitting the page to write the cache is a wasted few seconds of life. even worse if the change affected several pages.
i also add a mail statement at the end of my cache writer that alerts me if the cache write fails. good way to catch problems early.
of course the ultimate speed gainer for a server is to turn off your db and use flat files. cut out the mysql querying and you save yourself huge overhead. mysql should only be used on sites with highly active data. why have mysql running if your data only changes daily or weekly?
if u use flat files then u dont need a cache. its the same server load to serve a flat file page as it is a cached page. its all files. :)