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 ?>
相关文章
相关标签/搜索