轉自:http://www.blhere.com/1164.html
一、引論
PHP,一門最近幾年興起的web設計腳本語言,由於它的強大和可伸縮性,近幾年來得到長足的發展,php相比傳統的asp網站,在速度上有絕對的優勢,想mssql轉6萬條數據php如需要40秒,asp不下2分鍾.但是,由於網站的數據越來越多,我們渴求能更快速的調用數據,不必要每次都從數據庫掉,我們可以從其他的地方,比方一個文件,或者某個內存地址,這就是php的緩存技術,也就是Cache技術.
二、分析深入
一般來說,緩存的目的是把數據放在一個地方讓訪問的更快點,毫無疑問,內存是最快的,但是,幾百M的數據能往內存放么?這不現實,當然,有的時候臨時放如服務器緩存,如ob_start()這個緩存頁面開啟的話在發送文件頭之前頁面內容都被緩存在內存中,知道等頁面輸出自動清楚或者等待 ob_get_contents的返回,[或者被ob_end_clean顯示的清除,這在靜態頁面的生成中能很好的利用,在模板中能得到很好的體現,我的這篇文章深入的討論了:
談PHP生成靜態頁面,這是一種方式,但這是臨時性的,不是解決我們問題的好方法.
另外,在asp中有一對象application,可以保存公用的參數,這也算點緩存,但在php,我至今沒看到開發者產出這種對象,的確,沒必要.asp.net的頁面緩存技術就用的是viewstate,而cache就是文件關聯,(不一定准確),文件被修改,更新緩存,文件沒被修改而且不超時(注釋1),就讀取緩存,返回結果,就是這個思路,看看這個源碼:
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
<?php
/* PHP代碼 */ class cache{ /*Class Name: cache Des cription: control to cache data,$cache_out_time is a array to save cache date time out. Version: 1.0 Author: 老農 cjjer Last modify:2006-2-26 Author URL:http://www.cjjer.com */ 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['s cript_NAME']; $url .= (!emptyempty($_SERVER['QUERY_STRING'])) ? '?' . $_SERVER['QUERY_STRING'] : ''; } return $url; } function warn($errorstring){ echo "<b><font color='red'>發生錯誤:<pre>".$errorstring."</pre></font></b>"; } 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 <b>".date('l dS \of F Y h:i:s A')."</b>,過期時間是:".date('l dS \of F Y h:i:s A',time()+$this->expireTime)."----------"; $this->cache_page($cacheFile,$data); } return $data; } /* 下面我打斷這個代碼逐行解釋. php學習之家http://www.444p.com 三、程序透析 這個緩存類(類沒什么好怕的.請繼續看)名稱是cache,有2個屬性: private $cache_dir; private $expireTime=180; $cache_dir是緩存文件所放的相對網站目錄的父目錄, $expireTime(注釋一)是我們緩存的數據過期的時間,主要是這個思路: 當數據或者文件被加載的時候,先判斷緩存文件存在不,返回false ,文件最后修改時間和緩存的時間和比當前時間大不,大的話說明緩存還沒到期,小的話返回false,當返回false的時候,讀取原始數據,寫入緩存文件中,返回數據., 接着看程序: php學習之家http://www.444p.com */ 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屬性設置為這個文件夾名稱,我們的所有緩存文件都是在這個 文件夾下面的. php學習之家 */ function __destruct(){ echo 'Cache class bye.'; } //這是class類的析構函數,為了演示,我們輸出一個字符串表示我們釋放cache類資源成功. php學習之家 function warn($errorstring){ echo "<b><font color='red'>發生錯誤:<pre>".$errorstring."</pre></font></b>"; } /* 這個方法輸出錯誤信息. php學習之家 */ function get_url() { if (!isset($_SERVER['REQUEST_URI'])) { $url = $_SERVER['REQUEST_URI']; }else{ $url = $_SERVER['s cript_NAME']; $url .= (!empty($_SERVER['QUERY_STRING'])) ? '?' . $_SERVER['QUERY_STRING'] : ''; } return $url; } /* 這個方法返回當前url的信息,這是我看國外很多人的cms系統這樣做,主要是緩存x.php?page=1,x.php?page=2, 等這種文件的,這里列出是為了擴展的這個cache類功能的. www.444p.com */ 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讀取到原來的類型. php學習之家 */ 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 <b>".date('l dS \of F Y h:i:s A')."</b>,過期時間是:".date('l dS \of F Y h:i:s A',time()+$this->expireTime)."----------"; $this->cache_page($cacheFile,$data); } return $data; } /* 這個函數是我們調用的方法,可以寫成接口的方法,由傳入參數判斷文件存在不,文件最后修改時間+expireTime的時間是不是過了當前時間(大於的話說明沒有過期),如果文件不存在或者已經過期,重新加載原始數據,這里,為了簡單期間,我們是直接源是字符串,您可以把cache類繼承某類,取到數據庫的數據.(注釋2) php學習之家 四、補充說明,結語 注釋一 :這個緩存的時間您可以自己調,可以根據時間情況讀取數組,xml,緩存等,請按照您的方便,值得一提的是緩存的時間(也就是緩存的key)也用緩存控制,.這在cms系統中被廣泛使用,他們把要更新的key放在緩存中,非常容易控制全戰. php學習之家 注釋二: php5開始支持類繼承,這是讓人興奮的,把網站全局休息寫在一個配置的類里面,再寫與數據層交互的類(如與MySQL交互的類),我們的這個cache類繼承數據交互的類,可以非常容易的讀取數據庫,這是外話,此處不再展開,有時間和大家詳談. 特別說明,這個類文件針對的php5以上版本,其他版本的請不要使用類. */ ?> |
