When your application requires fetching resources from other Web sites, it's never a good idea to fetch it from the remote site upon every visit to your site. I needed this to incorporate Flickr, Twitter, and Google Buzz into my own site. So I wrote this Cache class. Instead of using file_get_contents($url) to fetch an external resource, simply use $cache->get($url) instead. Everything is transparent, and the cache will refresh itself every hour.
<?php
class Cache {
private $dir;
public function __construct($dir) {
if (!file_exists($dir)) mkdir($dir, 0777, true);
if (!is_writable($dir)) {
throw new Exception('Cache directory is not writable!');
}
$this->dir = $dir;
}
public function refresh($url) {
if (preg_match('/^http[s]{0,1}:\/\//i', $url) != 0) {
$contents = file_get_contents($url);
if ($contents === '') {
return;
}
$this->writeToFile($this->getCacheFileName($url), $contents);
}
}
public function set($url, $contents) {
$this->writeToFile($this->getCacheFileName($url), $contents);
}
public function get($url) {
$localFile = $this->getCacheFileName($url);
$mustRefresh = (isset($_GET['cache']) && $_GET['cache'] === '0');
if ($mustRefresh || !file_exists($localFile)) {
$this->refresh($url);
}
if (time() - filemtime($localFile) > 60 * 60) {
$this->refresh($url);
}
return file_get_contents($localFile);
}
public function getWithoutRefreshing($url) {
return file_get_contents($this->getCacheFileName($url));
}
public function exists($url) {
return file_exists($this->getCacheFileName($url));
}
public function getLastRefreshed($url) {
return filemtime($this->getCacheFileName($url));
}
private function getCacheFileName($url) {
$parsed = parse_url($url);
$fileName = $this->dir . '/' . $parsed['host'];
$fileName .= isset($parsed['path'])
? str_replace(array('/', ':', '&', '=', '@'), '_', $parsed['path'])
: '';
$fileName .= isset($parsed['query'])
? str_replace(array('/', ':', '&', '=', '@'), '_', $parsed['query'])
: '';
return $fileName . '.cache';
}
private function writeToFile($fileName, $data) {
$fh = fopen($fileName, 'w') or die('Unable to write to file '.$fileName);
fwrite($fh, $data);
fclose($fh);
chmod($fileName, 0777);
}
public function clear() {
$this->rm_rf($this->dir);
}
private function rm_rf($dir) {
if (is_dir($dir)) {
foreach (scandir($dir) as $item){
if (!strcmp( $item, '.' ) || !strcmp( $item, '..' )) {
continue;
}
$this->rm_rf($dir . "/" . $item);
}
rmdir($dir);
}
else{
unlink($dir);
}
}
}
?>