phpcms 源碼分析二:

  此次是逆雪寒的common.inc.php第二部分:php

  

  1 <?php
  2         /*    
  3         明天放假了.今天在寫點羅.放假沒空寫了.要陪老婆,你們看了有什麼不明白的.能夠跟帖問.我懂的我會回答.謝謝
  4         [/php]
  5         
  6         繼續::
  7         
  8         2007-12-21
  9         
 10         吃完中午開始分析了點代碼.時間很少.
 11         [php]
 12         /*
 13         代碼講解分析: 逆雪寒. 2007 - 12 - 21 
 14         */
 15 
 16         /*
 17          加載整站的配置參數文件。通常的程序都會有這個文件。作什麼的呢?好比一些數據庫鏈接地址。用戶名,密碼等。
 18         須要用到的參數都定義在這個文件裏面。這樣之後配置變了。咱們只要改動下這個文件裏面的
 19         變量值就好。是否是很方便呢。呵呵.  在這裏說下 require() 這個加載函數。
 20         require 和 include 都是用來加載其餘PHP文件用的。但他們是有區別的。
 21         require 函數:是"預解釋"函數。就是程序一加載,就執行了require函數。而include  呢。
 22         是個過程加載函數。咱們能夠在邏輯裏好比: if 裏面使用include 來動態的加載其餘程序片斷。而require 就不行。
 23         */
 24         require PHPCMS_ROOT.'/config.inc.php';
 25         
 26 
 27         /*
 28          顧名思義: 這個就是加載語言包了。PHP的國際化目前作得最多的。就是直接用PHP文件來實現。
 29         在 phpcms.lang.php 文件裏面定義程序中要用到的中文信息。而後在程序一開始就加載。那裏程序裏面
 30         就可使用這個文件裏面的變量和一切。那麼就簡單了。模板上就不須要直接寫中文信息了。直接用這個文件裏面定義的變量等來替換。
 31         從而實現國際化。over!!!最好本身打開這個語言文件再加上本身思考下。就知道。原來如此簡單。
 32         */
 33         require PHPCMS_ROOT.'/languages/'.$CONFIG['language'].'/phpcms.lang.php';
 34         
 35 
 36         /*
 37          $CONFIG['rootpath']  這個就是全局配置文件 config.inc.php 文件裏面數據庫信息。等所有配置信息。
 38         在這裏把他們定義爲 常量。 爲何須要定義爲常量呢。由於做者感受這樣寫爽羅。呵呵。其實由於後面
 39         用到這兩個變量多。因此乾脆定義爲常量。方便使用。再多說一個技巧: $CONFIG['rootpath']
 40         其實也能夠寫成 $CONFIG[rootpath]  可是最好不要這樣。爲何呢。由於PHP引擎會先判斷  rootpath 是否是常量。
 41         若是不是纔會認定     $CONFIG[rootpath]  是數組。 這樣性能上就差了一點點了。 
 42         再多說一個技巧: 爲何程序多數都用 '' 單引號呢而不用 "" 雙引號呢。由於這樣效率好, "" 雙引號。
 43         php引擎還會先檢查裏面是否有變量,若是有就解釋。而 '' 單引號不會作這一步的檢查。而直接就當成字符串了。因此效率上也會有一點點影響哦。
 44         */
 45         define('PHPCMS_PATH', $CONFIG['rootpath']);
 46         
 47         define('PHPCMS_CACHEDIR', $CONFIG['cachedir']);
 48         
 49 
 50         /*
 51          $CONFIG['enablephplog']  是否開啓錯誤日誌設置。這個設置在全局配置文件裏面.config.inc.php 。 
 52         這裏使用了 三目運算符   偶最喜歡用了。一些簡短的邏輯判斷。可使用 ? : ; 來實現比較簡潔
 53         set_error_handler() 這個函數就大有來頭了。php4裏面的典型自定義程序出錯後行爲的一個函數。
 54         十分好用。怎麼用呢? set_error_handler(函數) 的參數也是一個函數。這個函數。反映了程序出錯後行爲的。
 55         phpcms_error 函數存在 global.func.php 全局函數裏面。
 56         */
 57         $CONFIG['enablephplog'] ? set_error_handler('phpcms_error') 
 58                                 : error_reporting(E_ERROR | E_WARNING | E_PARSE);
 59 
 60         
 61         /*
 62          就是這個。 如今咱們慢慢來幹掉他。呵呵   這個自定義出錯信息函數默認帶有四個參數。 第一個參數 $errno 是程序出錯的等級。 
 63         第二參數是程序出錯的界面信息。第三是出現錯誤的程序文件名。
 64         第四是 第幾行出現錯誤。第五個參數。要不要都行是當前變量狀態的快照.看吧。
 65         咱們有這些信息後。想定義怎麼樣的錯誤信息給客戶看都很容易了是吧?但如今咱們是要生成錯誤日誌呢?
 66         這裏phpcms 做者是動態生成一個XML文件來作錯誤日誌的。不錯不錯.
 67         他使用了 in_array() 函數來實現(由於比較簡單,本身理解下) 
 68         只記錄 E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE 這三個級別的錯誤日誌信息。
 69         \n 是文本換行符  \t是製表符. 這裏他使用了一個比較漂亮而不經常使用的函數 wddx_serialize_value ()
 70         wddx 其實也是一種 xml 。 wddx_serialize_value() 這個函數就是把通常變量以XML格式輸出。
 71         這樣咱們就不用本身模擬寫xml了。方便吧。呵呵 第一個參數就是: 要格式輸出的變量,第二個參數是輸出的xml的介紹信息.
 72         下面就是 error_log() 函數。這個函數十分有用了。就是生成錯誤日誌XML文件。不須要咱們fopen 了。
 73         方便吧。它還有不少功能。詳細的看手冊。chmod 設置日誌文件的權限是 可讀可寫可執行。  
 74         在php5中。我習慣使用 extends Exception 來定義本身的出錯信息。
 75         因此不多用 set_error_handle(). 若是沒開啓日誌功能。
 76         那麼 error_reporting(E_ERROR | E_WARNING | E_PARSE) 就運行了。把通常出錯信息先出過來。
 77         */
 78         function phpcms_error($errno, $errmsg, $filename, $linenum, $vars)
 79         {
 80             $filename = str_replace(PHPCMS_ROOT, '.', $filename);
 81             
 82             $filename = str_replace("\\", '/', $filename);  //  把win平臺的 \\ 換成  /兼容常見系統的路徑
 83             
 84             if(!defined('E_STRICT')) define('E_STRICT', 2048);
 85             
 86             $dt = date('Y-m-d H:i:s');
 87             
 88             $errortype = array (  
 89                     E_ERROR           => 'Error',
 90                     E_WARNING         => 'Warning',
 91                     E_PARSE           => 'Parsing Error',
 92                     E_NOTICE          => 'Notice',
 93                     E_CORE_ERROR      => 'Core Error',
 94                     E_CORE_WARNING    => 'Core Warning',
 95                     E_COMPILE_ERROR   => 'Compile Error',
 96                     E_COMPILE_WARNING => 'Compile Warning',
 97                     E_USER_ERROR      => 'User Error',
 98                     E_USER_WARNING    => 'User Warning',
 99                     E_USER_NOTICE     => 'User Notice',
100                     E_STRICT          => 'Runtime Notice'
101             );
102             
103             $user_errors = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE);
104             
105             $err = "<errorentry>\n";
106             
107             $err .= "\t<datetime>" . $dt . "</datetime>\n";
108             
109             $err .= "\t<errornum>" . $errno . "</errornum>\n";
110             
111             $err .= "\t<errortype>" . $errortype[$errno] . "</errortype>\n";
112             
113             $err .= "\t<errormsg>" . $errmsg . "</errormsg>\n";
114             
115             $err .= "\t<scriptname>" . $filename . "</scriptname>\n";
116             
117             $err .= "\t<scriptlinenum>" . $linenum . "</scriptlinenum>\n";
118             
119             if (in_array($errno, $user_errors))
120             {
121                 $err .= "\t<vartrace>" 
122                      . wddx_serialize_value($vars, "Variables")
123                      . "</vartrace>\n";
124             }
125             
126             $err .= "</errorentry>\n\n";
127             
128             echo $err;
129             
130             error_log($err, 3, PHPCMS_ROOT.'/data/php_error_log.xml');
131             
132             chmod(PHPCMS_ROOT.'/data/php_error_log.xml', 0777);
133         }
134         
135 
136         /*
137          定義session 的存儲路徑,session 其實 也是cookie 不過 session 是實如今服務器端的。安全但負載重點。
138         這樣作的好處?效率很好。若是你在虛擬主機的話。你們的session cookie 都放在了php.ini裏面設置的默認地方。
139         文件夾臃腫就會慢羅。是吧。第二就是安全羅。 記得必定要定義在 session_start()函數以前
140         */
141         if($CONFIG['sessionsavepath']) {
142             session_save_path($CONFIG['sessionsavepath']);
143         }
144 
145         session_start();
146 
147         /*
148          php5開始有時區的概念了。記得就行
149         */
150         if(function_exists('date_default_timezone_set')) { 
151             date_default_timezone_set($CONFIG['timezone']);
152         }
153         
154 
155         /*
156          設置頁面編碼.  php編碼有: 頁面編碼。數據庫編碼。文件內碼。若是三碼相同就通常不會出現亂碼. 文件內碼是什麼呢?
157         每一個文件都有本身的內部編碼。通常都用UTF8比較爽。怎麼改變文件內碼?你用DW也行  UE 也行。隨便。 
158         數據庫編碼那確定是要指定的了。mysql5開始也有字符集模式這個最好也設置這樣能夠兼容更多平臺。
159         頁面編碼:<meta http-equiv="Content-Type" c />  這句就是。通常的HTML頭文件都有。
160         那 還須要header('Content-type: text/html; charset='.$CONFIG['charset']);嗎?  
161         其實須要的。由於有些本身寫的提示層呀。或是文件裏沒指定頁面編碼的。就很容易出現亂碼那麼咱們就防範於未然。
162         header 一個編碼過去。那就OK了。多好。
163         */
164         header('Content-type: text/html; charset='.$CONFIG['charset']);
165         
166 
167         /*
168          函數 getenv() 是獲取環境變量。  環境變量: HTTP_CLIENT_IP 是獲取客戶端的IP 。
169         但有可能人家是經過代理來訪問你的程序的呢。那麼這時候就要用 環境變量:
170         HTTP_X_FORWARDED_FOR  了。 包括  getenv('REMOTE_ADDR')  $_SERVER['REMOTE_ADDR'] 
171         是獲取人家  IP的。反正碰羅。碰到那個能獲取就大工告成。
172         */
173         if(getenv('HTTP_CLIENT_IP') && 
174            strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown'))
175         {
176             $PHP_IP = getenv('HTTP_CLIENT_IP');
177         } 
178         
179         elseif(getenv('HTTP_X_FORWARDED_FOR') && 
180                strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown'))
181         {
182             $PHP_IP = getenv('HTTP_X_FORWARDED_FOR');
183         }
184         
185         elseif(getenv('REMOTE_ADDR') && 
186                strcasecmp(getenv('REMOTE_ADDR'), 'unknown'))
187         {
188             $PHP_IP = getenv('REMOTE_ADDR');
189         }
190         
191         elseif(isset($_SERVER['REMOTE_ADDR']) && 
192                $_SERVER['REMOTE_ADDR'] && 
193                strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown'))
194         {
195             $PHP_IP = $_SERVER['REMOTE_ADDR'];
196         }
197         
198         preg_match("/[\d\.]{7,15}/", $PHP_IP, $ipmatches);
199         
200         $PHP_IP = $ipmatches[0] ? $ipmatches[0] : 'unknown';
201         
202 
203 
204         $PHP_TIME = time();
205 
206         /*
207          獲取當前運行的腳本名:  剛開始看是否是有點亂呢。 咋沒用if else 呢。
208         看這樣的東西。咱們最好從右看到左。這樣比較好明白點。$_SERVER['SCRIPT_NAME']
209         $_SERVER['PHP_SELF']  $_SERVER['ORIG_PATH_INFO'] 這三個服務器全局變量都是獲取 當前腳本名的
210         。主要看服務器當前環境了。那個存在的就獲取那個。
211         isset() 函數 十分有用。 測試一個變量是否已經定義。 
212         注: $a= NULL ; isset($a) 這樣會返回false的哦。 
213         注意 isset 和empty 兩個函數的用法。用得很差會出大問題的。本身看手冊。  
214         */
215         $PHP_SELF = isset($_SERVER['PHP_SELF']) 
216                         ? $_SERVER['PHP_SELF'] 
217                         : (isset($_SERVER['SCRIPT_NAME']) 
218                                 ? $_SERVER['SCRIPT_NAME'] 
219                                 : $_SERVER['ORIG_PATH_INFO']);
220         
221 
222 
223         $PHP_QUERYSTRING = $_SERVER['QUERY_STRING'];
224         
225         $PHP_DOMAIN = $_SERVER['SERVER_NAME'];
226         
227         $PHP_REFERER = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
228         
229         //測試服務器是否啓動了ssl 鏈接若是是的話。就用https://安全鏈接來進行通行
230         $PHP_SCHEME = $_SERVER['SERVER_PORT'] == '443' ? 'https://' : 'http://';
231          
232         $PHP_PORT = $_SERVER['SERVER_PORT'] == '80' ? '' : ':'.$_SERVER['SERVER_PORT'];
233         
234         $PHP_SITEURL = $PHP_SCHEME.$PHP_DOMAIN.$PHP_PORT.PHPCMS_PATH;
235 
236         /*
237          獲取當前腳本的URL
238         */
239         $PHP_URL = $PHP_SCHEME.$PHP_DOMAIN.$PHP_PORT.$PHP_SELF.($PHP_QUERYSTRING ? '?'.$PHP_QUERYSTRING : '');
240         
241 
242         /*
243         下面這部分相對複雜了點。但不要緊。慢慢講解. 首先緩存只針對前臺.因此咱們一開始就判斷.這個腳本是運行在前臺的而不是在後臺 !defined('IN_ADMIN') 來判斷.
244         而後呢.再看客戶配置 config.inc.php文件是否開啓了緩存. ==2 就是開啓了. .接着開始用一系列的規則來找出緩寸的文件名和目錄:
245         以 腳本名:xx.php和後續傳遞的參數 ?xx=ee&bb=jj 他兩的字符串的MD5 .以這個md5串來定義出了緩存目錄.和緩存文件 .
246         接着再判斷這個緩存文件是否存在和是否沒過緩存有效期.若是沒有就返回這個緩存文件的名字.
247         而後到主菜了. 最後一個if邏輯是作什麼的呢? 不知道你們有沒見過 這樣的網址:http://www.beihai.com/dd.php/xx-23/cc-22.html  
248         他們其實都算是僞靜態.優化URL用的.咋看起來還很象靜態.爽. 但你可能想.這樣的地址.咱們寫PHP程序的.怎麼獲取get 變量呢?  
249         最後if 就是解答這個問題的. 先剝離url來獲取  傳遞的字符串.而後 str_replace 來把 '/'  '-'  替換成標準的  '&' '='
250         好象:  http://www.beihai.com/dd.php&xx=23&cc=22 
251         看這樣你應該看明白了吧.而後用 parse_str() 函數來把xx 變 $xx=23   cc 變 $cc=22
252         php真是什麼都給你想到了.強.看明白了吧.OK.過了.
253         */
254         $db_file = $db_class = 'db_'.$CONFIG['database'];
255         
256         //若是不是在後臺。 常量 IN_ADMIN 是後臺標誌
257         if(!defined('IN_ADMIN'))  
258         {
259             if($CONFIG['dbiscache']) {
260                 $db_file .= '_cache';
261             }
262             
263             // 若是在config.inc.php 裏面開啓了緩存
264             if($CONFIG['phpcache'] == '2')  
265             {
266                 //把腳本名和後面的get信息 md5加密,以此來生成下面的緩存目錄和緩存文件
267                 $cachefileid = md5($PHP_SELF.'?'.$PHP_QUERYSTRING);
268                  
269                 //緩存目錄
270                 $cachefiledir = PHPCMS_ROOT.'/data/phpcache/'.substr($cachefileid, 0, 2).'/';  
271                 
272                 //緩存文件: xxx.html 格式
273                 $cachefile = $cachefiledir.$cachefileid.'.html';  
274                  
275                     if(file_exists($cachefile) && 
276                       ($PHP_TIME < @filemtime($cachefile) + $CONFIG['phpcacheexpires']))
277                     {   
278                         //若是緩存文件存在和緩存沒有過時效,那麼就返回緩存文件名
279                          require $cachefile;
280                          
281                          exit;
282                     }
283             }
284             
285             //獲取傳遞過來的變量。有什麼用的呢?請看下面解釋
286             if($PHP_QUERYSTRING && 
287                preg_match("/^(.*)\.(htm|html|shtm|shtml)$/", $PHP_QUERYSTRING, $urlvar)) 
288             {
289                 parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1]));
290             }
291         }
292 
293 
294         /*
295         恩.終於把common.inc.php 這個文件大概講解完了. 這個文件裏面包含了不少東西.都是些挺不錯的思想.你們應該好好學習.這樣咱們寫出來的PHP程序會更增強壯.
296         :lol: ,偶如今晚上都在邊陪老婆邊看電影邊弄linux 的C,仍是學習 階段  因此時間有點緊.白天在公司擠點時間出來分析代碼羅.
297         
298         對於phpcms 我也是第一次接觸.之前沒裝過也沒用過.如今也沒詳細用過.因此我看到代碼講什麼我就講什麼.沒具體講PHPCMS的應用等.但願理解.
299         
300         若是我分析代碼分析得不合理.請指出.共同進步學習.謝謝
301         */
302 ?>
相關文章
相關標籤/搜索