【PHP开源代码栏目提醒】:网学会员鉴于大家对PHP开源代码十分关注,论文会员在此为大家搜集整理了“PHPCMS 整站代码分析 - 毕业设计”一文,供大家参考学习
PHPCMS 整站
代码分析讲解1ztPHP 编程 2008-11-29 22:40 阅读23 评论0 字号 大 中 小 转自phpchina 作者逆雪寒一、include/common.inc.
php ltphp/
代码讲解分析 逆雪寒. 2007 - 12 - 20 /mtime explode microtime phpcms_starttime mtime1 mtime0/计算脚本开始运行的时间。
很常见的写法。
最后结算还在程序运行的终点位置。
讲到了在给各位说。
/unsetLANG _REQUEST HTTP_ENV_VARS HTTP_POST_VARS HTTP_GET_VARS HTTP_POST_FILES HTTP_COOKIE_VARS/把 HTTP_ENV_VARS HTTP_POST_VARS 全局变量设置为 NULL 因为
php4.1.0以上默认以 _POST 来替代。
unset后防止程序运行在低版本会出现安全等问题。
比如变量注入/set_magic_quotes_runtime0 //地球人都知道。
关了字符窜入库自动转意 比如 my name is onx 转成 my name is on x 为了最大的程序性能所以我们关掉吧哈哈defineIN_PHPCMS TRUE /程序入口标记。
为什么需要这个东西呢。
就好比你进一个小区保安大哥哥肯定要你签字或是挂个鸟牌证明你是从正门进来的。
防止你翻墙进入去偷东西搞破坏。
这个入口标记也有这个功能。
在这里定义了一个常量 IN_PHPCMS 为 TRUE 然后我在其他程序文件里面检查这个标记。
如果不存在或不为真那么就基本可以肯定你这个家伙是个小偷来的。
人可能翻墙进入。
但程序怎么翻墙呢。
只要在
php.ini文件里面激活 allow_url_fopen选项include 就可以包含 URL 地址了。
你想下如果你有个 放密码的
PHP文件。
如果给人家include 了以后。
你怕不怕。
/definePHPCMS_ROOT str_replacequotquot / substrdirname__FILE__ 0 -8/为了程序产品的跨平台。
自动获取程序的安装目录路径 定义为 PHPCMS_ROOT 常量。
方便以后程序使用。
建议大家都这样做哦/require PHPCMS_ROOT./include/global.func.
php /包含 全局函数 global.func.
php 文件。
里面放了些程序全局都有需要用的函数.大家看到了吧。
常量 PHPCMS_ROOT 已经发挥作用。
这样程序给人家发布到了 二级目录下。
也不需要人家手动改整站根目录路径了。
自己好好理解下。
。
。
。
。
/search_arr arrayquot/ union /iquotquot/ select /iquotquot/ update /iquotquot/ outfile /iquotquot/ or /iquot/quot/ union /iquot 这个是正则的写法不懂正则的自己百度找教程来学。
这里不详细说了/replace_arr array union select update outfile or /看这个意思很明了。
union 连接两条SQL语句。
outfile : 主要用来导出数据库资料到其他介质上。
干啥字要定义这两个变量呢 在 global.func.
php 文件前面已经加载里面有个函数 strip_sql 各位可以看下。
function strip_sqlstringglobal search_arrreplace_arrreturn is_arraystring array_mapstrip_sql string : preg_replacesearch_arr replace_arr string函数里面定义了这两个变量为 global全局变量。
那么函数里就可以直接使用了。
先讲解下这个函数吧。
顾名思义这个函数是过滤字符窜里面的SQL语句使得关键的SQL语句单词失效。
主要过滤那些SQL语句呢。
主要是这几个关键字: union select update outfile or 等。
因为这几个SQL字是极度容易在_GET传输中给截注.这个函数写得实在精妙。
is_array 来判断 string 是否为数组。
如果 是 就 array_map 函数来递归过滤 string数组里面的每一个单元. 每个单元是一个字符窜吧当递归调用 strip_sql 以后 is_array判断 string 肯定为假了因为string已经不是数组而是字符窜。
所以 执行 preg_replace函数。
这个函数很好理解了。
就是替换了。
/_POST strip_
sql_POST_GET strip_sql_GET_COOKIE strip_sql_COOKIE/使用strip_sql函数来过滤 _POST _GET _COOKIE一般不是
开源的站。
很少过SQL关键字过滤。
不过这个也是冒很大风险的。
/unsetsearch_arr replace_arr/unset 使用过但以后不需要的变量。
这个是很好的习惯。
第一不会浪费内存。
如果变量存了大量的数据字节而后你的程序是一直不需要用的。
那么就会很浪费内存。
拉底程序性能 . 哈哈。
真很书面。
反正是好习惯我们都要学习的拉。
/magic_quotes_gpc get_magic_quotes_gpc // get_magic_quotes_gpc检测gpc是否系统自动转意。
gpc 是什么呢 GET POST COOKIE 来来去去就这几个东西罗。
会返回 真或假ifmagic_quotes_gpc_POST new_addslashes_POST_GET new_addslashes_GET/判断一下
系统是否打开了自动对gpc进行转意这个选择。
如果是的话就不需要我们自动转意了。
如果不是那么还是要老百姓的手段。
自己动手丰衣足食。
来看下也是在global.func.
php 文件里面定义的这个函数 其实是一个封装好的
php的 addslashes 函数的函数。
PHP都自己有了为什么还要自己封装成函数呢理由很简单。
为了以后的扩展更改容易罗。
如果我们一开始就全部用 addslashes 这个函数来对 进行转意的话。
那么以后随着程序的发展。
我可能想多过滤个 之类的那如何是好呢所以为了以后孩子的成长。
我们还是最好封起来吧。
记住以后有可能会边的东西。
最好都封装成模块。
函数 。
类。
这样程序的灵活度就上去了。
function new_addslashesstringifis_arraystring return addslashesstringforeachstring as key gt val stringkey new_addslashesvalreturn string这个函数也是写得贼好。
也是同时考虑过滤 字符窜或数组也是使用了 传归。
看下就应该明白了吧。
这个不用说了。
我们要学下这个思路这个方法方式哦。
这样才能进步。
哈哈。
我们要懂模仿。
/extract_POST EXTR_OVERWRITEextract_GET EXTR_OVERWRITE/嘿。
extract 前面加个 鸡蛋做什么呢抑制错误的。
还不懂的话。
自己百度了。
为什么用extract函数呢. 平时我们
程序 是不是要常使用 _POST _GET来获取传递的变量呀。
是不是感觉贼麻烦呀。
比如 _POSTxx 这样接受是挺好。
但写多了很麻烦是吧。
我是感觉麻烦。
我现在想直接就 xx就可以获取传递过来的东西。
那怎么办呢。
就用了 extract函数来实现这么一个技巧。
这个技巧在discuz 论坛上也有应用。
/unset_POST _GET/unset 好处不用说了吧。
释放 _POST _GET 数组 因为已经不需要他们了。
/gt/
代码讲解分析 逆雪寒. 2007 - 12 - 2 /require PHPCMS_ROOT./config.inc.
php/加栽整站的配置参数文件。
一般的程序都会有这个文件。
做什么的呢比如一些数据库连接地址。
用户名密码等。
需要用到的参数都定义在这个文件里面。
这样以后配置变了。
我们只要改动下这个文件里面的变量值就好。
是不是很方便呢。
呵呵. 在这里说下 require 这个加载函数。
require 和 include 都是用来加载其他
PHP文件用的。
但他们是有区别的。
require 函数是quot预解释quot函数。
就是程序一加载就执行了require函数。
而include 呢。
是个过程加载函数。
我们可以在逻辑里比如 if 里面使用include 来动态的加载其他程序片段。
而require 就不行。
/require PHPCMS_ROOT./languages/.CONFIGlanguage./phpcms.lang.
php/顾名思义 这个就是加载语言包了。
的国际化目前做得最多的。
就是直接用文件来实现。
在 phpcms.lang.
php 文件里面定义程序中要用到的中文信息。
然后在程序一开始就加载。
那里程序里面就可以使用这个文件里面的变量和一切。
那么就简单了。
模板上就不需要直接写中文信息了。
直接用这个文件里面定义的变量等来替换。
从而实现国际化。
over最好自己打开这个语言文件再加上自己思考下。
就知道。
原来如此简单。
/definePHPCMS_PATH CONFIGrootpathdefinePHPCMS_CACHEDIR CONFIGcachedir/CONFIGrootpath 这个就是全局配置文件 config.inc.
php 文件里面数据库信息。
等全部配置信息。
在这里把他们定义为 常量。
为什么需要定义为常量呢。
因为作者感觉这样写爽罗。
呵呵。
其实因为后面用到这两个变量多。
所以干脆定义为常量。
方便使用。
再多说一个技巧 CONFIGrootpath 其实也可以写成 CONFIGrootpath 但是最好不要这样。
为什么呢。
因为引擎会先判断 rootpath 是不是常量。
如果不是才会认定 CONFIGrootpath 是数组。
这样性能上就差了一点点了。
再多说一个技巧 为什么程序多数都用 单引号呢而不用 quotquot 双引号呢。
因为这样效率好 quotquot 双引号。
php引擎还会先检查里面是否有变量如果有就解释。
而 单引号不会做这一步的检查。
而直接就当成字符窜了。
所以效率上也会有一点点影响哦。
/CONFIGenablephplog set_error_handlerphpcms_error : error_reportingE_ERROR E_WARNING E_PARSE/CONFIGenablephplog 是否开启错误日志设置。
这个设置在全局配置文件里面.config.inc.
php 。
这里使用了 三目运算符 偶最喜欢用了。
一些简短的逻辑判断。
可以使用 : 来实现比较简洁set_error_handler 这个函数就大有来头了。
php4里面的典型自定义程序出错后行为的一个函数。
十分好用。
怎么用呢 set_error_handler函数 的参数也是一个函数。
这个函数。
反映了程序出错后行为的。
phpcms_error 函数存在 global.func.
php 全局函数里面。
function phpcms_errorerrno errmsg filename linenum varsfilename str_replacePHPCMS_ROOT . filename filename str_replacequotquot / filename // 把win平台的 换成 /兼容常见系统的路径 ifdefinedE_STRICT defineE_STRICT 2048dt dateY-m-d H:i:serrortype array E_ERROR gt Error E_WARNING gt Warning E_PARSE gt Parsing Error E_NOTICE gt Notice E_CORE_ERROR gt Core Error E_CORE_WARNING gt Core Warning E_COMPILE_ERROR gt Compile Error E_COMPILE_WARNING gt Compile Warning E_USER_ERROR gt User Error E_USER_WARNING gt User Warning E_USER_NOTICE gt User Notice E_STRICT gt Runtime Notice user_errors arrayE_USER_ERROR E_USER_WARNING E_USER_NOTICEerr quotlterrorentrygtnquoterr . quottltdatetimegtquot . dt . quotlt/datetimegtnquoterr . quottlterrornumgtquot . errno . quotlt/errornumgtnquoterr . quottlterrortypegtquot . errortypeerrno . quotlt/errortypegtnquoterr . quottlterrormsggtquot . errmsg . quotlt/errormsggtnquoterr . quottltscriptnamegtquot . filename . quotlt/scriptnamegtnquoterr . quottltscriptlinenumgtquot . linenum . quotlt/scriptlinenumgtnquotif in_arrayerrno user_errors err . quottltvartracegtquot . wddx_serialize_valuevars quotVariablesquot . quotlt/vartracegtnquoterr . quotlt/errorentrygtnnquotecho errerror_logerr 3 PHPCMS_ROOT./data/
php_error_log.xmlchmodPHPCMS_ROOT./data/
php_error_log.xml 0777就是这个鸟蛋。
现在我们慢慢来干掉他。
呵呵 这个自定义出错信息函数默认带有四个参数。
第一个参数 errno 是程序出错的等级。
第二参数是程序出错的界面信息。
第三是出现错误的程序文件名。
第四是 第几行出现错误。
第五个参数。
要不要都行是当前变量状态的快照.看吧。
我们有这些信息后。
想定义怎么样的错误信息给客户看都很容易了是吧但现在我们是要生成错误日志呢这里phpcms 作者是动态生成一个文件来做错误日志的。
不错不错. 他使用了 in_array 函数来实现因为比较简单自己理解下 只记录 E_USER_ERROR E_USER_WARNING E_USER_NOTICE 这三个级别的错误日志信息。
n 是文本换行符 t是制表符. 这里他使用了一个比较漂亮而不
常用的函数 wddx_serialize_value wddx 其实也是一种
xml 。
wddx_serialize_value 这个函数就是把一般变量以格式输出。
这样我们就不用自己模拟写xml了。
方便吧。
呵呵 第一个参数就是 要格式输出的变量第二个参数是输出的xml的介绍信息. 下面就是 error_log 函数。
这个函数十分有用了。
就是生成错误日志文件。
不需要我们fopen 了。
方便吧。
它还有很多功能。
详细的看手册。
chmod 设置日志文件的权限是 可读可写可执行。
在
php5中。
我习惯使用 extends Exception 来定义自己的出错信息。
所以很少用 set_error_handle. 如果没开启日志功能。
那么 error_reportingE_ERROR E_WARNING E_PARSE 就运行了。
把一般出错信息先出过来。
/ifCONFIGsessionsavepath session_save_pathCONFIGsessionsavepath/定义session 的存储路径session 其实 也是cookie 不过 session 是实现在服务器端的。
安全但负载重点。
这样做的好处效率很好。
如果你在虚拟主机的话。
大家的session cookie 都放在了
php.ini里面设置的默认地方。
文件夹臃肿就会慢罗。
是吧。
第二就是安全罗。
记得一定要定义在 session_start函数之前/session_startiffunction_existsdate_default_timezone_set date_default_timezone_setCONFIGtimezone/
php5开始有时区的概念了。
记得就行/headerContent-type: text/html charset.CONFIGcharset/设置页面编码.
php编码有 页面编码。
数据库编码。
文件内码。
如果三码相同就一般不会出现乱码. 文件内码是什么呢每个文件都有自己的内部编码。
一般都用比较爽。
怎么改变文件内码你用也行 也行。
随便。
数据库编码那肯定是要指定的了。
mysql5开始也有字符集模式这个最好也设置这样可以兼容更多平台。
页面编码ltmeta http-equivquotContent-Typequot c /gt 这句就是。
一般的头文件都有。
那 还需要headerContent-type: text/html charset.CONFIGcharset吗 其实需要的因为有些自己写的提示层呀。
或是文件里没指定页面编码的。
就很容易出现乱码那么我们就防范于未然。
header 一个编码过去。
那就了。
多好。
/ifgetenvHTTP_CLIENT_IP ampamp strcasecmpgetenvHTTP_CLIENT_IP unknownPHP_IP getenvHTTP_CLIENT_IPelseifgetenvHTTP_X_FORWARDED_FOR ampamp strcasecmpgetenvHTTP_X_FORWARDED_FOR unknownPHP_IP getenvHTTP_X_FORWARDED_FORelseifgetenvREMOTE_ADDR ampamp strcasecmpgetenvREMOTE_ADDR unknownPHP_IP getenvREMOTE_ADDRelseifisset_SERVERREMOTE_ADDR ampamp _SERVERREMOTE_ADDR ampamp strcasecmp_SERVERREMOTE_ADDR unknownPHP_IP _SERVERREMOTE_ADDRpreg_matchquot/d.715/quot
PHP_IP ipmatchesPHP_IP ipmatches0 ipmatches0 : unknown/函数 getenv 是获取环境变量。
环境变量 HTTP_CLIENT_IP 是获取客户端的 。
但有可能人家是通过代理来访问你的程序的呢。
那么这时候就要用 环境变量HTTP_X_FORWARDED_FOR 了。
包括 getenvREMOTE_ADDR _SERVERREMOTE_ADDR 都是获取人家 的。
反正碰罗。
碰到那个能获取就大工告成。
/
PHP_TIME timePHP_SELF isset_SERVER
PHP_SELF _SERVERPHP_SELF : isset_SERVERSCRIPT_NAME _SERVERSCRIPT_NAME : _SERVERORIG_PATH_INFO/获取当前运行的脚本名: 刚开始看是不是有点乱呢。
咋没用if else 呢。
看这样的东西。
我们最好从右看到左。
这样比较好明白点。
_SERVERSCRIPT_NAME _SERVERPHP_SELF _SERVERORIG_PATH_INFO 这三个服务器全局变量都是获取 当前脚本名的。
主要看服务器当前环境了。
那个存在的就获取那个。
isset 函数 十分有用。
测试一个变量是否已经定义。
注 a NULL isseta 这样会返回false的哦。
注意 isset 和empty 两个函数的用法。
用得不好会出大
问题的。
自己看手册。
/
PHP_QUERYSTRING _SERVERQUERY_STRINGPHP_DOMAIN _SERVERSERVER_NAMEPHP_REFERER isset_SERVERHTTP_REFERER _SERVERHTTP_REFERER :
PHP_SCHEME _SERVERSERVER_PORT 443 https:// : http:// //测试服务器是否启动了ssl 连接如果是的话。
就用https://安全连接来进行通行
PHP_PORT _SERVERSERVER_PORT 80 : :._SERVERSERVER_PORTPHP_SITEURL
PHP_SCHEME.
PHP_DOMAIN.
PHP_PORT.PHPCMS_PATHPHP_URL
PHP_SCHEME.
PHP_DOMAIN.
PHP_PORT.
PHP_SELF.
PHP_QUERYSTRING .
PHP_QUERYSTRING : /获取当前脚本的/db_file db_class db_.CONFIGdatabaseifdefinedIN_ADMIN //如果不是在后台。
常量 IN_ADMIN 是后台标志ifCONFIGdbiscache db_file . _cacheifCONFIGphpcache 2 // 如果在config.inc.
php 里面开启了缓存 cachefileid md5
PHP_SELF..
PHP_QUERYSTRING //把脚本名和后面的get信息 md5加密以此来生成下面的缓存目录和缓存文件 cachefiledir PHPCMS_ROOT./data/phpcache/.substrcachefileid 0 2./ //缓存目录 cachefile cachefiledir.cachefileid..html //缓存文件 xxx.html 格式 iffile_existscachefile ampamp
PHP_TIME lt filemtimecachefile CONFIGphpcacheexpires //如果缓存文件存在和缓存没有过期效那么就返回缓存文件名 require cachefile exit ifPHP_QUERYSTRING ampamp preg_matchquot/..htmhtmlshtmshtml/quot
PHP_QUERYSTRING urlvar //获取传递过来的变量。
有什么用的呢请看下面解释 parse_strstr_replacearray/ - arrayamp urlvar1/上面这部分相对复杂了点。
但没关系。
慢慢讲解 首先缓存只针对前台所以我们一开始就判断这个脚本是运行在前台的而不是在后台 definedIN_ADMIN 来判断然后呢再看客户配置 config.inc.
php文件是否开启了缓存 2 就是开启了 接着开始用一系列的规则来找出缓寸的文件名和目录 以 脚本名xx.
php和后续传递的参数 xxeeam
pbbjj 他两的字符窜的MD5 .以这个md5窜来定义出了缓存目录和缓存文件 接着再判断这个缓存文件是否存在和是否没过缓存有效期如果没有就返回这个缓存文件的名字.然后到主菜了 最后一个if逻辑是做什么的呢 不知道大家有没见过 这样的网址urlhttp://www.beihai.com/dd.
php/xxhttp://www.beihai.com/dd.
php/xx/url23/cc-22.html 他们其实都算是伪静态优化用的咋看起来还很象静态爽 但你可能想这样的地址我们写程序的怎么获取get 变量呢 最后if 就是解答这个问题的 先剥离url来获取 传递的字符窜.然后 str_replace 来把 / - 替换成标准的 amp 好象: urlhttp://www.beihai.com/dd.phpampxx23ampcc22http://www.beihai.com/dd.phpampxx23ampcc22/url 看这样你应该看明白了吧然后用 parse_str 函数来把xx 变 xx23 cc 变 cc22
php真是什么都给你想到了强看明白了吧过了/require PHPCMS_ROOT./include/.db_file..class.
php // 包含数据库操作类下章详说require PHPCMS_ROOT./include/tag.func.
php //遇到再说require PHPCMS_ROOT./include/extension.inc.
php //遇到再说db new db_class // 实例化数据库类db-gtconnectCONFIGdbhost CONFIGdbuser CONFIGdbpw CONFIGdbname CONFIGpconnect //连接数据库db-gtiscache CONFIGdbiscache //是否开启缓存db-gtexpires CONFIGdbexpires //缓存时间ifcache_readtable.phprequire_once PHPCMS_ROOT./include/cache.func.
php cache_all //生成所有缓存/cache_read 函.