此次是逆雪寒的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 ?>