PHPCMS V9 框架代码分析(入口程序)

  PHPCMS是采用MVC设计模式开发,基于模块和操作的方式进行访问,采用单一入口模式进行项目部署和访问,无论访问任何一个模块或者功能,只有一个统一的入口。

  入口程序是在前期处理用户请求的引导程序。它是唯一一个可以被最终用户直接请求运行的。

  PHPCMS V9的入口程序(index.php)如下:

复制代码
 1 <?php
 2 /**
 3  *  index.php PHPCMS 入口
 4  *
 5  * @copyright            (C) 2005-2010 PHPCMS
 6  * @license                http://www.phpcms.cn/license/
 7  * @lastmodify            2010-6-1
 8  */
 9 //PHPCMS根目录
10 
11 define('PHPCMS_PATH', dirname(__FILE__).DIRECTORY_SEPARATOR);
12 
13 include PHPCMS_PATH.'/phpcms/base.php';
14 
15 pc_base::creat_app();
16 
17 ?>
复制代码

  第一行:定义项目的根路径,后面文件查找依赖此变量。

  DIRECTORY_SEPARATOR(目录分隔符)是一个返回与操作系统相关的路径分隔符的内置命令,不需要任何定义与包含即可直接使用。由于windows上习惯性的使用\作为文件分隔符,但是在linux上人家是不认识这个标识的,人家只认识/,于是就要引入下面这个php内置常量:DIRECTORY_SEPARATOR。

  第二行:根据项目根路径引入base.php文件,文件内容如下:

复制代码
  1 <?php
  2 /**
  3  *  base.php PHPCMS框架入口文件
  4  *
  5  * @copyright            (C) 2005-2010 PHPCMS
  6  * @license                http://www.phpcms.cn/license/
  7  * @lastmodify            2010-6-7
  8  */
  9 
 10 /*
 11 * 定义常量IN_PHPCMS
 12 */
 13 // 定义常量IN_PHPCMS
 14 define('IN_PHPCMS', true);
 15 
 16 /*
 17 * 定义PHPCMS框架路径、缓存文件夹地址
 18 */
 19 //PHPCMS框架路径
 20 define('PC_PATH', dirname(__FILE__).DIRECTORY_SEPARATOR);
 21 if(!defined('PHPCMS_PATH')) define('PHPCMS_PATH', PC_PATH.'..'.DIRECTORY_SEPARATOR);
 22 
 23 //缓存文件夹地址
 24 define('CACHE_PATH', PHPCMS_PATH.'caches'.DIRECTORY_SEPARATOR);
 25 
 26 /*
 27 * 主机协议、当前访问的主机名、来源、系统开始时间
 28 */
 29 //主机协议
 30 define('SITE_PROTOCOL', isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == '443' ? 'https://' : 'http://');
 31 
 32 //当前访问的主机名
 33 define('SITE_URL', (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ''));
 34 
 35 //来源
 36 define('HTTP_REFERER', isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '');
 37 
 38 //系统开始时间
 39 define('SYS_START_TIME', microtime());
 40 
 41 /*
 42 * 加载共用函数库
 43 */
 44 //加载公用函数库
 45 pc_base::load_sys_func('global');
 46 pc_base::load_sys_func('extention');
 47 pc_base::auto_load_func();
 48 
 49 /*
 50 * 加载一些配置参数
 51 */
 52 pc_base::load_config('system','errorlog') ? set_error_handler('my_error_handler') : error_reporting(E_ERROR | E_WARNING | E_PARSE);
 53 
 54 //设置本地时差
 55 function_exists('date_default_timezone_set') && date_default_timezone_set(pc_base::load_config('system','timezone'));
 56 
 57 define('CHARSET' ,pc_base::load_config('system','charset'));
 58 //输出页面字符集
 59 header('Content-type: text/html; charset='.CHARSET);
 60 
 61 define('SYS_TIME', time());
 62 //定义网站根路径
 63 define('WEB_PATH',pc_base::load_config('system','web_path'));
 64 //js 路径
 65 define('JS_PATH',pc_base::load_config('system','js_path'));
 66 //css 路径
 67 define('CSS_PATH',pc_base::load_config('system','css_path'));
 68 //img 路径
 69 define('IMG_PATH',pc_base::load_config('system','img_path'));
 70 //动态程序路径
 71 define('APP_PATH',pc_base::load_config('system','app_path'));
 72 
 73 //应用静态文件路径
 74 define('PLUGIN_STATICS_PATH',WEB_PATH.'statics/plugin/');
 75 
 76 if(pc_base::load_config('system','gzip') && function_exists('ob_gzhandler')) 
 77 {
 78     ob_start('ob_gzhandler');
 79 } 
 80 else 
 81 {
 82     ob_start();
 83 }
 84 
 85 class pc_base
 86 {
 87     /**
 88      * 初始化应用程序
 89      */
 90     public static function creat_app() 
 91     {
 92         return self::load_sys_class('application');
 93     }
 94     /**
 95      * 加载系统类方法
 96      * @param string $classname 类名
 97      * @param string $path 扩展地址
 98      * @param intger $initialize 是否初始化
 99      */
100     public static function load_sys_class($classname, $path = '', $initialize = 1) 
101     {
102         return self::_load_class($classname, $path, $initialize);
103     }
104     
105     /**
106      * 加载应用类方法
107      * @param string $classname 类名
108      * @param string $m 模块
109      * @param intger $initialize 是否初始化
110      */
111     public static function load_app_class($classname, $m = '', $initialize = 1)
112     {
113         $m = empty($m) && defined('ROUTE_M') ? ROUTE_M : $m;
114         if (empty($m)) 
115             return false;
116         return self::_load_class($classname, 'modules'.DIRECTORY_SEPARATOR.$m.DIRECTORY_SEPARATOR.'classes', $initialize);
117     }
118     
119     /**
120      * 加载数据模型
121      * @param string $classname 类名
122      */
123     public static function load_model($classname) 
124     {
125         return self::_load_class($classname,'model');
126     }
127         
128     /**
129      * 加载类文件函数
130      * @param string $classname 类名
131      * @param string $path 扩展地址
132      * @param intger $initialize 是否初始化
133      */
134     private static function _load_class($classname, $path = '', $initialize = 1) 
135     {
136         static $classes = array();
137         if (empty($path)) 
138             $path = 'libs'.DIRECTORY_SEPARATOR.'classes';
139 
140         $key = md5($path.$classname);
141         if (isset($classes[$key])) 
142         {
143             if (!empty($classes[$key])) 
144             {
145                 return $classes[$key];
146             } 
147             else 
148             {
149                 return true;
150             }
151         }
152         if (file_exists(PC_PATH.$path.DIRECTORY_SEPARATOR.$classname.'.class.php')) 
153         {
154             include PC_PATH.$path.DIRECTORY_SEPARATOR.$classname.'.class.php';
155             $name = $classname;
156             if ($my_path = self::my_path(PC_PATH.$path.DIRECTORY_SEPARATOR.$classname.'.class.php')) 
157             {
158                 include $my_path;
159                 $name = 'MY_'.$classname;
160             }
161             if ($initialize) 
162             {
163                 $classes[$key] = new $name;
164             } 
165             else 
166             {
167                 $classes[$key] = true;
168             }
169             
170             return $classes[$key];
171         } 
172         else 
173         {
174             return false;
175         }
176     }
177     
178     /**
179      * 加载系统的函数库
180      * @param string $func 函数库名
181      */
182     public static function load_sys_func($func) 
183     {
184         return self::_load_func($func);
185     }
186     
187     /**
188      * 自动加载autoload目录下函数库
189      * @param string $func 函数库名
190      */
191     public static function auto_load_func($path='') 
192     {
193         return self::_auto_load_func($path);
194     }
195     
196     /**
197      * 加载应用函数库
198      * @param string $func 函数库名
199      * @param string $m 模型名
200      */
201     public static function load_app_func($func, $m = '') 
202     {
203         $m = empty($m) && defined('ROUTE_M') ? ROUTE_M : $m;
204         if (empty($m)) 
205             return false;
206         return self::_load_func($func, 'modules'.DIRECTORY_SEPARATOR.$m.DIRECTORY_SEPARATOR.'functions');
207     }
208     
209     /**
210      * 加载插件类库
211      */
212     public static function load_plugin_class($classname, $identification = '' ,$initialize = 1) 
213     {
214         $identification = empty($identification) && defined('PLUGIN_ID') ? PLUGIN_ID : $identification;
215         if (empty($identification)) 
216             return false;
217         return pc_base::load_sys_class($classname, 'plugin'.DIRECTORY_SEPARATOR.$identification.DIRECTORY_SEPARATOR.'classes', $initialize);
218     }
219     
220     /**
221      * 加载插件函数库
222      * @param string $func 函数文件名称
223      * @param string $identification 插件标识
224      */
225     public static function load_plugin_func($func,$identification) 
226     {
227         static $funcs = array();
228         $identification = empty($identification) && defined('PLUGIN_ID') ? PLUGIN_ID : $identification;
229         if (empty($identification)) 
230             return false;
231         $path = 'plugin'.DIRECTORY_SEPARATOR.$identification.DIRECTORY_SEPARATOR.'functions'.DIRECTORY_SEPARATOR.$func.'.func.php';
232         $key = md5($path);
233         if (isset($funcs[$key])) 
234             return true;
235         if (file_exists(PC_PATH.$path)) 
236         {
237             include PC_PATH.$path;
238         } 
239         else 
240         {
241             $funcs[$key] = false;
242             return false;
243         }
244         $funcs[$key] = true;
245         return true;
246     }
247     
248     /**
249      * 加载插件数据模型
250      * @param string $classname 类名
251      */
252     public static function load_plugin_model($classname, $identification) 
253     {
254         $identification = empty($identification) && defined('PLUGIN_ID') ? PLUGIN_ID : $identification;
255         $path = 'plugin'.DIRECTORY_SEPARATOR.$identification.DIRECTORY_SEPARATOR.'model';
256         return self::_load_class($classname,$path);
257     }
258     
259     /**
260      * 加载函数库
261      * @param string $func 函数库名
262      * @param string $path 地址
263      */
264     private static function _load_func($func, $path = '') 
265     {
266         static $funcs = array();
267         if (empty($path)) $path = 'libs'.DIRECTORY_SEPARATOR.'functions';
268         $path .= DIRECTORY_SEPARATOR.$func.'.func.php';
269         $key = md5($path);
270         if (isset($funcs[$key])) 
271             return true;
272         if (file_exists(PC_PATH.$path)) 
273         {
274             include PC_PATH.$path;
275         } 
276         else 
277         {
278             $funcs[$key] = false;
279             return false;
280         }
281         $funcs[$key] = true;
282         return true;
283     }
284     
285     /**
286      * 加载函数库
287      * @param string $func 函数库名
288      * @param string $path 地址
289      */
290     private static function _auto_load_func($path = '') 
291     {
292         if (empty($path)) $path = 'libs'.DIRECTORY_SEPARATOR.'functions'.DIRECTORY_SEPARATOR.'autoload';
293         $path .= DIRECTORY_SEPARATOR.'*.func.php';
294         $auto_funcs = glob(PC_PATH.DIRECTORY_SEPARATOR.$path);
295         if(!empty($auto_funcs) && is_array($auto_funcs)) 
296         {
297             foreach($auto_funcs as $func_path) 
298             {
299                 include $func_path;
300             }
301         }
302     }
303     /**
304      * 是否有自己的扩展文件
305      * @param string $filepath 路径
306      */
307     public static function my_path($filepath) 
308     {
309         $path = pathinfo($filepath);
310         if (file_exists($path['dirname'].DIRECTORY_SEPARATOR.'MY_'.$path['basename'])) 
311         {
312             return $path['dirname'].DIRECTORY_SEPARATOR.'MY_'.$path['basename'];
313         } 
314         else 
315         {
316             return false;
317         }
318     }
319     
320     /**
321      * 加载配置文件
322      * @param string $file 配置文件
323      * @param string $key  要获取的配置键
324      * @param string $default  默认配置。当获取配置项目失败时该值发生作用。
325      * @param boolean $reload 强制重新加载。
326      */
327     public static function load_config($file, $key = '', $default = '', $reload = false) 
328     {
329         static $configs = array();
330         if (!$reload && isset($configs[$file])) 
331         {
332             if (empty($key)) 
333             {
334                 return $configs[$file];
335             } 
336             elseif (isset($configs[$file][$key])) 
337             {
338                 return $configs[$file][$key];
339             } 
340             else 
341             {
342                 return $default;
343             }
344         }
345         $path = CACHE_PATH.'configs'.DIRECTORY_SEPARATOR.$file.'.php';
346         if (file_exists($path)) 
347         {
348             $configs[$file] = include $path;
349         }
350         if (empty($key)) 
351         {
352             return $configs[$file];
353         } 
354         else if (isset($configs[$file][$key])) 
355         {
356             return $configs[$file][$key];
357         } 
358         else 
359         {
360             return $default;
361         }
362     }
363 }
复制代码

  base.php文件为框架入口文件,包含实例化系统/模块类方法,调用系统/模块方法,系统常用常量等。为了便于理解,现按顺序分四部分解析:

  [1] 定义常量 IN_PHPCMS

define('IN_PHPCMS', true);

  在phpcms项目源码搜索关键字“IN_PHPCMS”,相关的代码语句有:

defined(‘IN_PHPCMS’) or exit('No permission resources.');

  以及:

defined('IN_PHPCMS') or exit('Access Denied.');

  defined:是用来检查常量是否已定义。

  注意:如果你要检查一个变量是否存在,请使用isset()。如果你要检查一个函数是否存在,使用function_exists()。defined()函数仅对constants常量有效:如果该名称的常量已定义,返回TURE;未定义则返回FALSE。

  or:如果or前面的代码语句执行失败(或者返回false、0、null),那么执行or到其后第一个分号前面的代码(但双引号的分号不算);如果or前面的代码执行成功(或者返回true、非0、非null),那么不执行or到其后第一个分号前面的代码。

  综上所述,phpcms为了代码不执行错误,每个执行文件都会判断是否包含了base.php文件,以减少错误。

  [2] 定义PHPCMS框架路径、缓存文件夹地址

  具体代码片段见上文base.php文件代码详细

  __FILE__ 返回文件的完整路径和文件名。如果用在被包含文件中,则返回被包含的文件名。

  __FILE__ 总是包含一个绝对路径(如果是符号连接,则是解析后的绝对路径,比如PHPCMS里面的 PC_PATH.’..’.DIRECTORY_SEPARATOR)

  dirname(__FILE__) 函数返回的是脚本所在的路径,不会返回当前的文件名称。如果b.php包含了dirname(__FILE__)相关代码,同时b.php被其他目录里的a.php文件require或者include已用的话,返回的依然是b.php所在的那个文件夹路径,而不是变成a.php文件所在目录。

  [3] 主机协议、当前访问的主机名、来源、系统开始时间

  $_SERVER['SERVER_PORT']:返回80是使用http协议访问

  $_SERVER['SERVER_PORT']:返回443是使用https协议访问

  [4] 加载共用函数库

1 //加载公用函数库
2 pc_base::load_sys_func('global');
3 pc_base::load_sys_func('extention');
4 pc_base::auto_load_func();

  很显然,类中静态方法调用,具体执行步骤见类pc_base(上文base.php文件中)的函数。

  头两句分别加载了/phpcms/libs/functions/global.func.php 和 /phpcms/libs/functions/extention.func.php文件。

  global.func.php是共用函数库。

  extension.func.php是用户自定义函数库。

  最后一句是加载/phpcms/libs/functions/autoload/文件夹下面 *.func.php 文件(详见函数注释)。

 

  第三行:pc_base是base.php定义的类,调用类方法create_app。

 

Good Good Study, Day  Day  Up.

顺序 选择 循环 总结

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin
avatar