一般來說,緩衝的目的是把資料放在一個地方讓訪問的更快點,毫無疑問,記憶體是最快的,但是,幾百M的資料能往記憶體放麼?這不現實,當然,有的時候臨時放如伺服器緩衝,如ob_start()這個快取頁面面開啟的話在傳送檔案頭之前頁面內容都被緩衝在記憶體中,知道等頁面輸出自動清楚或者等待 ob_get_contents的返回,或者被ob_end_clean顯示的清除,這在靜態頁面的產生中能很好的利用,在模板中能得到很好的體現,我的這篇文章深入的討論了:談PHP產生靜態頁面,這是一種方式,但這是臨時性的,不是解決我們問題的好方法。
另外,在asp中有一對象application,可以儲存公用的參數,這也算點緩衝,但在php,我至今沒看到開發人員產出這種對象,的確,沒必要。asp。net的頁面緩衝技術就用的是viewstate,而cache就是檔案關聯,(不一定準確),檔案被修改,更新緩衝,檔案沒被修改而且不逾時,就讀取緩衝,返回結果,就是這個思路,看看這個源碼:
class cache { /* Class Name: cache Description: control to cache data,$cache_out_time is a array to save cache date time out. */ private $cache_dir; private $expireTime=180;//緩衝的時間是 60 秒 function __construct($cache_dirname){ if(!@is_dir($cache_dirname)){ if(!@mkdir($cache_dirname,0777)){ $this->warn('快取檔案不存在而且不能建立,需要手動建立.'); return false; } } $this->cache_dir = $cache_dirname; }function __destruct(){ echo 'Cache class bye.'; } function get_url() { if (!isset($_SERVER['REQUEST_URI'])) { $url = $_SERVER['REQUEST_URI']; }else{ $url = $_SERVER['SCRIPT_NAME']; $url .= (!empty($_SERVER['QUERY_STRING'])) ? '?' . $_SERVER['QUERY_STRING'] : ''; } return $url; } function warn($errorstring){ echo "發生錯誤:".$errorstring.""; } function cache_page($pageurl,$pagedata){ if(!$fso=fopen($pageurl,'w')){ $this->warns('無法開啟快取檔案.');//trigger_error return false; } if(!flock($fso,LOCK_EX)){//LOCK_NB,排它型鎖定 $this->warns('無法鎖定快取檔案.');//trigger_error return false; } if(!fwrite($fso,$pagedata)){//寫入位元組流,serialize寫入其他格式 $this->warns('無法寫入快取檔案.');//trigger_error return false; } flock($fso,LOCK_UN);//釋放鎖定 fclose($fso); return true; } function display_cache($cacheFile){ if(!file_exists($cacheFile)){ $this->warn('無法讀取快取檔案.');//trigger_error return false; } echo '讀取快取檔案:'.$cacheFile; //return unserialize(file_get_contents($cacheFile)); $fso = fopen($cacheFile, 'r'); $data = fread($fso, filesize($cacheFile)); fclose($fso); return $data; } function readData($cacheFile='default_cache.txt'){ $cacheFile = $this->cache_dir."/".$cacheFile; if(file_exists($cacheFile)&&filemtime($cacheFile)>(time()-$this->expireTime)){ $data=$this->display_cache($cacheFile); }else{ $data="from here wo can get it from mysql database,update time is ".date('l dS of F Y h:i:s A').",到期時間是:".date('l dS of F Y h:i:s A',time()+$this->expireTime)."----------"; $this->cache_page($cacheFile,$data); } return $data; } } ?>
這個緩衝類有2個屬性:
private $cache_dir; private $expireTime=180;
$cache_dir是快取檔案所放的相對網站目錄的父目錄, $expireTime(注釋一)是我們緩衝的資料到期的時間,主要是這個思路: 當資料或者檔案被載入的時候,先判斷快取檔案存在不,返回false ,檔案最後修改時間和緩衝的時間和比目前時間大不,大的話說明緩衝還沒到期,小的話返回false,當返回false的時候,讀取未經處理資料,寫入快取檔案中,返回資料。
接著看程式:
function __construct($cache_dirname){ if(!@is_dir($cache_dirname)){ if(!@mkdir($cache_dirname,0777)){ $this->warn('快取檔案不存在而且不能建立,需要手動建立.'); return false; } } $this->cache_dir = $cache_dirname; }
當類第一次被執行個體的時候構造預設函數帶參數快取檔案名稱,如檔案不存在,建立一個有編輯許可權的檔案夾,建立失敗的時候拋出異常。然後把cache類的 $cache_dir屬性設定為這個檔案夾名稱,我們的所有快取檔案都是在這個檔案夾下面的。
function __destruct(){ echo 'Cache class bye.'; }
這是class類的解構函式,為了示範,我們輸出一個字串表示我們釋放cache類資源成功。
function warn($errorstring){ echo "發生錯誤:".$errorstring.""; }
這個方法輸出錯誤資訊。
function get_url() { if (!isset($_SERVER['REQUEST_URI'])) { $url = $_SERVER['REQUEST_URI']; }else{ $url = $_SERVER['SCRIPT_NAME']; $url .= (!empty($_SERVER['QUERY_STRING'])) ? '?' . $_SERVER['QUERY_STRING'] : ''; } return $url; }
這個方法返回當前url的資訊,這是我看國外很多人的cms系統這樣做,主要是緩衝x。php?page=1,x。php?page=2,等這種檔案的,這裡列出是為了擴充的這個cache類功能的。
function cache_page($pageurl,$pagedata){ if(!$fso=fopen($pageurl,'w')){ $this->warns('無法開啟快取檔案.');//trigger_error return false; } if(!flock($fso,LOCK_EX)){//LOCK_NB,排它型鎖定 $this->warns('無法鎖定快取檔案.');//trigger_error return false; } if(!fwrite($fso,$pagedata)){//寫入位元組流,serialize寫入其他格式 $this->warns('無法寫入快取檔案.');//trigger_error return false; } flock($fso,LOCK_UN);//釋放鎖定 fclose($fso); return true; }
cache_page方法分別傳入的是緩衝的檔案名稱和資料,這是把資料寫到檔案裡的方法,先用fopen開啟檔案,然後調用控制代碼鎖定這個檔案,然後用fwrite寫入檔案,最後釋放這個控制代碼,任何一步發生錯誤將拋出錯誤。 您可能看到這個注釋:
寫入位元組流,serialize寫入其他格式,順便一提的是如果我們要把一個數組,(可以從MySQL資料庫裡面select查詢除了的結果)用serialize函數寫入,用unserialize讀取到原來的類型。
function display_cache($cacheFile){ if(!file_exists($cacheFile)){ $this->warn('無法讀取快取檔案.');//trigger_error return false; } echo '讀取快取檔案:'.$cacheFile; //return unserialize(file_get_contents($cacheFile)); $fso = fopen($cacheFile, 'r'); $data = fread($fso, filesize($cacheFile)); fclose($fso); return $data; }
這是由檔案名稱讀取緩衝的方法,直接開啟檔案,讀取全部,如果檔案不存在的或者無法讀取的話返回false,當然,你感到不人性的話,可以重建緩衝。
function readData($cacheFile='default_cache.txt'){ $cacheFile = $this->cache_dir."/".$cacheFile; if(file_exists($cacheFile)&&filemtime($cacheFile)>(time()-$this->expireTime)){ $data=$this->display_cache($cacheFile); }else{ $data="from here wo can get it from mysql database,update time is ".date('l dS of F Y h:i:s A').",到期時間是:".date('l dS of F Y h:i:s A',time()+$this->expireTime)."----------"; $this->cache_page($cacheFile,$data); } return $data; }
這個函數是我們調用的方法,可以寫成介面的方法,由傳入參數判斷檔案存在不,檔案最後修改時間+expireTime的時間是不是過了目前時間 (大於的話說明沒有到期),如果檔案不存在或者已經到期,重新載入未經處理資料,這裡,為了簡單期間,我們是直接源是字串,您可以把cache類繼承某類, 取到資料庫的資料。
注釋一:這個緩衝的時間您可以自己調,可以根據時間情況讀取數組,xml,緩衝等,請按照您的方便,值得一提的是緩衝的時間(也就是緩衝的key)也用緩衝控制,。這在cms系統中被廣泛使用,他們把要更新的key放在緩衝中,非常容易控制全戰。
注釋二:php5開始支援類繼承,這是讓人興奮的,把網站全域休息寫在一個配置的類裡面,再寫與資料層互動的類(如與MySQL互動的類),我們的這個cache類繼承資料互動的類,可以非常容易的讀取資料庫,這是外話,此處不再展開,有時間和大家詳談。
特別說明,這個類檔案針對的php5以上版本,其他版本的請不要使用類。
http://www.bkjia.com/PHPjc/752412.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/752412.htmlTechArticle一般來說,緩衝的目的是把資料放在一個地方讓訪問的更快點,毫無疑問,記憶體是最快的,但是,幾百M的資料能往記憶體放麼?這不現實,當...