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.
顺序 选择 循环 总结