phpcms 源碼分析五:文件緩存實現

  此次是逆雪寒的文件緩存實現代碼分析:php

  

  1         /*
  2         [/php]
  3         
  4         PHPCMS的文本緩存實現:
  5         
  6         [php] 
  7         <?php 
  8         
  9         /*
 10         這個文件裏面全是有關生成文本緩存的函數。文本緩存是個好東西。通常的項目,咱們用不着內存緩存 : memcached  ,文本搞定。
 11         原理是這樣的: 咱們在後臺是否是能夠設置不少有關網站的參數。而這些參數不少都是固定的。就不變化的。都存到咱的數據庫上。而咱們程序那裏呢
 12         每次都要訪問數據庫讀出參數來進行咱們程序中的操做。首先數據庫查詢是個很耗硬盤IO資源的一個東西,因此文本緩存恰好能減輕數據庫那邊的承重。
 13         咱們在程序開始就把數據庫裏面的配置都轉化爲數組 等  放到  php文件裏面。這樣咱們能夠直接訪問php文件而不用每次都訪問數據庫了。  
 14         php文本緩存其實成了咱們程序和數據庫的一箇中間件。 因此咱們本身寫本身的文本緩存的時候其實要實現的很簡單:  
 15         讀數據庫  ->  寫到PHP文件 ->  程序中include ;來吧。開始文本緩存學習 
 16         */
 17         
 18         defined('IN_PHPCMS') or exit('Access Denied');
 19         
 20         // 生成全部緩存的總操做函數
 21         function cache_all()  
 22         {
 23             // 生成全部的數據庫表名,表名是根據數據庫裏面當前的表名而生成。請看這個函數的詳細分析
 24             cache_table();
 25              
 26             // 包含表常量
 27             require_once PHPCMS_CACHEDIR.'table.php'; 
 28             
 29             cache_common();
 30             
 31             cache_member_group();
 32             
 33             $modules = cache_module();
 34             
 35             $channelids = cache_channel(0);
 36             
 37             $keyids = array_merge($modules, $channelids);
 38             
 39             foreach($keyids as $keyid)
 40             {
 41                   $catids = cache_categorys($keyid);
 42                   
 43                   if(is_array($catids))
 44                   {
 45                        foreach($catids as $catid)
 46                        {
 47                         cache_category($catid);
 48                        }
 49                   }
 50             } 
 51             
 52             cache_type(0);
 53             
 54             return TRUE;
 55         }
 56         
 57         function cache_common()
 58         {
 59             global $db;
 60             
 61             // 查詢全部能用的模塊
 62             $query = $db->query("SELECT module,name,iscore,iscopy,isshare,moduledir,moduledomain FROM "
 63                                 .TABLE_MODULE." WHERE disabled=0"); 
 64             
 65             while($r = $db->fetch_array($query))
 66             {
 67                   $r['linkurl'] = '';
 68 
 69                   // 若是模塊存在目錄的就取它目錄地址
 70                   if($r['module'] != 'phpcms' && $r['iscopy'] == 0) {
 71                       $r['linkurl'] = linkurl($r['moduledomain'] 
 72                                     ? dir_path($r['moduledomain']) 
 73                                     : $r['moduledir'].'/');
 74                   }
 75                   
 76                   unset($r['moduledomain']);
 77               
 78                   $key = $r['module'];
 79               
 80                   $data[$key] = $r; 
 81             }
 82             
 83             // 存到緩存數組,等一下一塊兒把 $CACHE 數組寫到文本里去
 84             $CACHE['module'] = $data; 
 85             
 86             $data = array();
 87             
 88             // 羅列能用的頻道列表
 89             $query = $db->query("SELECT channelid, module, channelname, channeldir, channeldomain, 
 90                                  channelpic, introduce, style, islink, linkurl, cat_html_urlruleid, 
 91                                  item_html_urlruleid, special_html_urlruleid, cat_php_urlruleid, 
 92                                  item_php_urlruleid, special_php_urlruleid FROM ".TABLE_CHANNEL
 93                                  ." WHERE disabled=0 ORDER by listorder");
 94              
 95             while($r = $db->fetch_array($query))
 96             {
 97                   $r['linkurl'] = linkurl($r['linkurl']);
 98               
 99                   $key = $r['channelid'];
100               
101                   $data[$key] = $r;
102             }
103             
104             // 存到緩存數組
105             $CACHE['channel'] = $data;
106              
107             $data = array();
108             
109             // 查詢 phpcms這個模塊的設置信息,你們能夠看下數據庫這個表內容。setting 字段裏面的信息是通過serialize 函數串行化的
110             $r = $db->get_one("SELECT setting FROM ".TABLE_MODULE." WHERE module='phpcms'");
111 
112             /*
113              * 因此取出的內容要unserialize 反串行.我是挺喜歡使用serialize 函數的。
114              * 他能夠實現把一個數組存到數據庫或把一個對象存到數據庫。或是拿來GET傳遞都行。
115              * 太強了。你們能夠試用下。可能你項目某個地方須要用到哦。
116              */
117             $CACHE['phpcms'] = unserialize($r['setting']);
118             
119             $fields = array();
120             
121             // 下載模塊的信息,請本身看下這個表的數據就明白
122             $result = $db->query("SELECT * FROM ".TABLE_FIELD." ORDER BY fieldid"); 
123                 
124             while($r = $db->fetch_array($result))
125             {
126                   $tablename = $r['tablename'];
127               
128                   $fields[$tablename] .= ','.$r['name'];
129             }
130             
131             $CACHE['field'] = $fields;
132             
133             // 開始把$CACHE 數組寫到 common.php 這個文本緩存裏。你們能夠本身去打開這個文件看下內容。一切瞭然
134             cache_write('common.php', $CACHE); 
135 
136             return $CACHE;
137         }
138         
139         // 更新文本緩存。最好在後臺操做使用。由於PHP的文件flock 文件鎖在某些平臺使用不是很好。會出現多用戶同寫一個文件從而破壞緩存文件
140         function cache_update($action = '')
141         {
142             global $db;
143             
144             $data=array();
145             
146             switch($action)
147             {
148                   case 'keylink':
149                        $query=$db->query("SELECT linktext,linkurl FROM ".TABLE_KEYLINK." where passed=1");
150                
151                        while($r=$db->fetch_array($query))
152                        {
153                           $data[]=$r;
154                        }
155                   break;
156                   
157                   case 'reword':
158                        $query = $db->query("SELECT word,replacement FROM ".TABLE_REWORD." where passed=1");
159                        
160                        while($r = $db->fetch_array($query))
161                        {
162                         $data[]=$r;
163                        }
164                   break;
165                   
166                   default:
167                        $actions = array('keylink','reword');
168                        
169                        array_map('cache_update', $actions);
170                        
171                        return TRUE;
172             }
173             
174             cache_write('cache_'.$action.'.php', $data);
175             
176             return $data;
177         }
178         
179         function cache_table()
180         {
181             global $db,$CONFIG;
182             
183             /*
184              顯示數據庫裏面的全部表名
185             */
186             $query = $db->query("SHOW TABLES FROM `".$CONFIG['dbname']."`");
187     
188     
189             while($r = $db->fetch_row($query))
190             {
191                   $table = $r[0];
192               
193                   // 尋找表前綴等於 $CONFIG['tablepre'] (在config.inc.php裏設置) @@表前綴還有這個做用 嘿嘿
194                   if(preg_match("/^".$CONFIG['tablepre']."/i", $table)) 
195                   {
196                        $tablename = str_replace($CONFIG['tablepre'], 'table_', $table);
197                        
198                        // $data['table_xx'] = xx; 形式   只能意會下了
199                        $data[$tablename] = $table;    
200                 }
201             }
202             
203             // $db->free_result()  這個類方法實際上是調用了函數:mysql_free_result() 函數 
204             // 主要是爲了清除數據庫大量的查詢而佔用的內存。仍是有必要的哦
205             $db->free_result($query);
206               
207             // 常量 PHPCMS_CACHEDIR 在 common.inc.php 裏面定義的。你們不記得了去看看吧。
208             // 是存放phpcms 緩存目錄的路徑,這裏意思是:若是緩存目錄不存在
209             if(!is_dir(PHPCMS_CACHEDIR)) 
210             {
211                 // 若是緩存目錄不存在那麼就建立
212                   dir_create(PHPCMS_CACHEDIR);
213                    
214                   // 建立編譯後的PHP模板目錄,有關phpcms模板引擎編寫。在下一章合適就開講
215                   dir_create($CONFIG['templatescachedir']); 
216                   /*
217                   dir_create() 函數爲建立 目錄函數。PHPCMS本身封裝的,剛看了下。phpcms 挺強。
218                   這個函數還能夠經過ftp 來建立目錄。這樣就能夠解決一些 開啓了安全模式下的服務器對於建立目錄等出現的問題
219                   由於涉及到PHP FTP 知識。因此打算講解到下面再說。
220                   */
221             }
222 
223             /*
224              cache_write() 函數在global.func.php裏面定義的。是把 已經從數據庫取出來的數組信息寫到 PHP文本上去。
225              @@文本緩存關鍵的一步  廢話少說上菜:
226             */
227             cache_write('table.php', $data , 'constant'); //不少朋友說找不到phpcms 表常量在那裏定義的。就是在這裏。
228         
229           function cache_write($file, $string, $type = 'array')
230           {
231                  // 檢測 $string 內容是字符串的呢仍是數組的,是數組的那就繼續 ..
232                if(is_array($string))
233                {
234                     $type = strtolower($type);
235                       
236                     // 而後再判斷這個函數的模式標誌 ,是否爲數組模式,默認爲數組模式
237                     if($type == 'array')
238                     {
239                         /*這個太關鍵了。由於咱們把數據庫的信息寫到文本上去的時候。是以符合PHP語法的格式寫進去的。爲何呢?@@ 
240                          * 十分廢話,由於若是不是以PHP格式寫到文件裏面去,那麼這個PHP文件怎麼能給咱們include 進程序運行調用呢? 
241                          * 呵呵。 知道這一點就真的明白文本緩存的實現了。忒簡單。 這裏使用了個小技巧:使用了 var_export() 函數
242                          * 這個函數會返回一個變量的字符串形式。這個函數太有幫助了。若是沒有這個函數,咱們還要本身想辦法實現呢。
243                          * 本身寫一次文本緩存就明白了。會碰到這個問題的。 '\n' 這個是文本文件的換行。初學者 別把<br> 和 '\n' 搞混羅。 
244                          * 一個是html 的 一個是文本文件的。
245                          */
246                         $string = "<?php\n return ".var_export($string,TRUE).";\n?>"; 
247                     }
248                     
249                     // 之內容形式
250                     elseif($type == 'constant') 
251                     {
252                          $data='';
253                          
254                          foreach($string as $key => $value) $data .= "define('".strtoupper($key)."','".addslashes($value)."');\n";
255                          
256                          // 若是之內容形式的話。就不是寫數組到文本里面了。而是把內容都定義成常量。
257                          $string = "<?php\n".$data."\n?>";
258                     }
259                    }
260                
261                    // file_put_contents()函數 是PHP5才支持的 效率最好。建議使用
262                    $strlen = file_put_contents(PHPCMS_CACHEDIR.$file, $string);
263                
264                    // 設置目錄 爲可讀可寫可執行
265                    chmod(PHPCMS_CACHEDIR.$file, 0777); 
266                
267                    // 返回寫到文本的字節數
268                    return $strlen; 
269               }
270               
271             // 再說多一個讀 緩存文件的操做函數  :上菜
272               function cache_read($file, $mode = 'i')
273               {
274                   $cachefile = PHPCMS_CACHEDIR.$file;
275             
276                   if(!file_exists($cachefile)) {
277                       return array();
278                   }
279             
280                   return $mode == 'i' ? include $cachefile : file_get_contents($cachefile);
281                }
282           
283                // 讀緩存其實就是 include php 緩存文件。 講完走人
284     
285                return $data;
286         }
287         /*
288         phpcms 的全部數據庫表名 都用根據數據庫當前的表名來用常量來進行定義。我認爲這樣設計不是很好。
289         不夠靈活:好比若是咱們更改數據庫的一個表名的話。那麼會出現找不到表的錯誤信息。
290         並且想要修復還很麻煩。就是說不能隨便更改表名了。不推薦你們這樣寫。咱們能夠把表名都定義在一個PHP文件裏面。
291         這樣咱們之後要改某個表名,就很方便了。
292         */
293 
294         function cache_module($module = '')
295         {
296             global $db;
297             if($module)
298             {
299                 // 模塊具體信息
300                   $r = $db->get_one("SELECT setting,module,name,iscopy,moduledir,moduledomain FROM "
301                                     .TABLE_MODULE." WHERE module='$module'");
302                    
303                   if($r['setting'])
304                   {
305                       // 講過了反串行。由於裏面信息是串行化後再存到數據庫的
306                        $setting = unserialize($r['setting']); 
307                   }
308               
309                   $setting['name'] = $r['name'];
310               
311                   $setting['moduledir'] = $r['moduledir'];
312               
313                   $setting['moduledomain'] = $r['moduledomain'];
314               
315                   $setting['linkurl'] = '';
316               
317                   if($r['module'] != 'phpcms' && $r['iscopy'] == 0)
318                   {
319                       $setting['linkurl'] = linkurl($r['moduledomain'] 
320                                           ? dir_path($r['moduledomain']) 
321                                           : $r['moduledir'].'/');
322                         
323                       cache_categorys($module);
324                   }
325               
326                   unset($r['moduledomain']);
327               
328                   cache_write($module.'_setting.php', $setting);
329               
330                   return $setting;
331             }
332             
333             else
334             {
335                   $query = $db->query("SELECT module FROM ".TABLE_MODULE
336                                       ." WHERE disabled=0 ORDER by moduleid");
337                   
338                   while($r = $db->fetch_array($query))
339                   {
340                        cache_module($r['module']);
341                        
342                        $modules[] = $r['module'];
343                 }
344                 
345                   return $modules;
346             }
347         }
348         
349         function cache_channel($channelid = 0)
350         {
351             global $db;
352             
353             if($channelid)
354             {
355                   $data = $db->get_one("SELECT * FROM ".TABLE_CHANNEL
356                                        ." WHERE channelid=$channelid");
357                   
358                   if($data && !$data['islink'])
359                   {
360                        if($data['setting'])
361                        {
362                           $setting = unserialize($data['setting']);
363                         unset($data['setting']);
364                         $data = is_array($setting) ? array_merge($data, $setting) : $data;
365                        }
366                        
367                        $data['linkurl'] = linkurl($data['linkurl']);
368                        
369                        cache_write('channel_'.$channelid.'.php', $data);
370            
371                        cache_categorys($channelid);
372            
373                        return $data;
374                   }
375             }
376             
377             else
378             {
379                   $query = $db->query("SELECT channelid FROM ".TABLE_CHANNEL
380                                       ." WHERE islink=0 AND disabled=0 ORDER by channelid");
381               
382                 while($r = $db->fetch_array($query))
383                   {
384                       cache_channel($r['channelid']);
385                
386                       $channelids[] = $r['channelid'];
387                   }
388                   
389                   return $channelids;
390             }
391         }
392         
393         function cache_categorys($keyid)
394         {
395             global $db, $PHPCMS, $CHANNEL;
396             
397             $urlpre = '';
398             
399             if(is_numeric($keyid)) 
400             {
401                   $keyid = intval($keyid);
402               
403                   $module = $CHANNEL[$keyid]['module'];
404                     
405                   $sql = " channelid=$keyid ";
406             }
407             
408             else
409             {
410                     $sql = " module='$keyid' ";
411             }
412             
413             $catids = $data = array();
414                 
415             $query = $db->query("SELECT module,channelid,catid,catname,style,introduce,catpic,islink,catdir,
416                                  linkurl,parentid,arrparentid,parentdir,child,arrchildid,items,itemordertype,
417                                  itemtarget,ismenu,islist,ishtml,htmldir,prefix,urlruleid,item_prefix,item_html_urlruleid,
418                                  item_php_urlruleid FROM ".TABLE_CATEGORY." WHERE $sql ORDER by listorder,catid");
419             
420             while($r = $db->fetch_array($query))
421             {
422                   $r['linkurl'] = str_replace($PHPCMS['index'].'.'.$PHPCMS['fileext'], '', $r['linkurl']);
423                  
424                   $r['linkurl'] = $urlpre 
425                                 ? preg_replace("|^".$urlpre."|", '', $r['linkurl']) 
426                                 : linkurl($r['linkurl']);
427               
428                   $catid = $r['catid'];
429                     
430                   $data[$catid] = $r;
431               
432                   $catids[] = $catid;
433             }
434             
435             // 寫緩存羅。
436             if($data) {
437                 cache_write('categorys_'.$keyid.'.php', $data); 
438             }
439             
440             return $catids;
441         }
442         
443         function cache_category($catid)
444         {
445             global $db,$PHPCMS;
446             
447             if(!$catid) {
448                 return FALSE;
449             }
450                 
451             $data = $db->get_one("SELECT * FROM ".TABLE_CATEGORY
452                                  ." WHERE catid=$catid");
453             
454             $setting = unserialize($data['setting']);
455             
456             unset($data['setting']);
457             
458             $data = is_array($setting) ? array_merge($data, $setting) : $data;
459             
460             $data['linkurl'] = linkurl(str_replace($PHPCMS['index'].'.'.$PHPCMS['fileext'], '', $data['linkurl']));
461             
462             cache_write('category_'.$catid.'.php', $data);
463             
464             return $data;
465         }
466         
467         function cache_type($keyid=0)
468         {
469             global $db;
470             
471             if($keyid)
472             {
473                 $result = $db->query("SELECT * FROM ".TABLE_TYPE
474                                      ." WHERE keyid='$keyid'");
475                  $data = array();
476                  
477                  while($r = $db->fetch_array($result))
478                  {
479                        $r['introduce'] = $r['introduce']
480                                        ? $r['introduce']
481                                        : ' ';
482               
483                        $data[$r['typeid']] = $r;
484                  }
485                  
486                  if($data)
487                  {
488                        cache_write('type_'.$keyid.'.php', $data);
489                  }
490               
491                  return $data;
492             }
493             else 
494             {
495                   $modules = array();
496               
497                   $query = $db->query("SELECT module FROM ".TABLE_MODULE
498                                       ." WHERE disabled=0 ORDER by moduleid");
499                   
500                   while($r = $db->fetch_array($query))
501                   {
502                        $modules[] = $r['module'];
503                 }  
504                   
505                 $channelids = array();
506                   
507                 $query = $db->query("SELECT channelid FROM ".TABLE_CHANNEL
508                                     ." WHERE islink=0 AND disabled=0 ORDER by channelid");
509                   
510                   while($r = $db->fetch_array($query))
511                   {
512                        $channelids[] = $r['channelid'];
513                   }
514               
515                   $modulechannels = array_merge($modules, $channelids);
516                   
517                   foreach($modulechannels as $m)
518                   {
519                        $result = $db->query("SELECT * FROM ".TABLE_TYPE." WHERE keyid='$m'");
520                        
521                        $TYPE = array();
522                        
523                        while($r = $db->fetch_array($result))
524                        {
525                         $r['introduce'] = $r['introduce']? $r['introduce']:' ';
526                     
527                         $TYPE[$r['typeid']] = $r;
528                        }
529                
530                        cache_write('type_'.$m.'.php',$TYPE);
531                   }
532 
533                   return $modulechannels;  
534             }
535         }
536         
537         function cache_member_group()
538         {
539             global $db;
540             
541             // 用戶組信息
542             $query = $db->query("SELECT * FROM ".TABLE_MEMBER_GROUP." ORDER BY groupid"); 
543             
544             while($r = $db->fetch_array($query))
545             {
546                   $groupid = $r['groupid'];
547                   cache_write('member_group_'.$groupid.'.php', $r);
548                   $data[$groupid] = $r;
549             }
550             
551             // 明白了吧。寫緩存羅
552             cache_write('member_group.php', $data); 
553             
554             return $data;
555         }
556         
557         function cache_banip()
558         {
559             global $db, $PHP_TIME;
560             
561             $result = $db->query("SELECT ip,overtime FROM ".TABLE_BANIP
562                                  ." WHERE ifban=1 and overtime>=$PHP_TIME order by id desc ");
563             
564             while($r = $db->fetch_array($result))
565             {
566                   $data[] = array('ip'=>$r['ip'],
567                                   'overtime'=>$r['overtime']);
568             }
569             
570             $db->free_result($result);
571             
572             cache_write('banip.php', $data);
573             
574             return $data;
575         }
576         
相關文章
相關標籤/搜索