比較全面的一個PHP緩存類解析


轉自: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以上版本,其他版本的請不要使用類.
*/

?>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM