PHPCMS
整站代码分析讲解(四) 这个讲
phpcms
的数据库类
和
phpcms
的文本缓存的实现
.
看了看 都是很简单的东西
.
大家看着我注释慢慢看吧
.
慢慢理解
,
最好能装了
PHPCMS
在来看
.
因为这样可以看下它的数据库结构信息
.
可以帮助理解
. 不明白的继续问吧
. 首先是数据库类
,phpcms
的数据库 分
mysql
和
mssql
版本
. MSSQL
版本的我就不说了
.
他们主要的
sql
语句不同点就在于我们分页常用到的
limit
语句
.
所以
.
在
mssql
数据库类驱动里
.
他做了个挺好的封装
.
让
MYSQL
和
MSSQL
在
SQL
语句方面的差异性就很小了
.
可以说
PHPCMS
你可以随便转换数据库只要在代码中换下数据库类驱动就行
.
[Copy to clipboard]
[ - ] CODE: <?php /** mysql
数据库类。写得比较简单。也没什么好说的。大家自己看下理解下。 然后就可以跳过了。 */ defined('IN_PHPCMS') or exit('Access Denied'); /** 这个东西是不是很熟呀。对了。在上一章已经讲过了。也已经在上一章的
common.inc.php
启动文件里面定义了
IN_PHPCMS
所以在以下的
PHP
文件里都检测下是否是人为
”
跳墙
“
进来的。是就中断 */ /** * Mysql
数据库类,支持
Cache
功能 */ class db_mysql { /** * MySQL
连接标识 * @var resource */ var $connid; /** *
整型变量用来计算被执行的
sql
语句数量 * @var int */ var $querynum = 0; /** *
数据库连接,返回数据库连接标识符 * @param string
数据库服务器主机 * @param string
数据库服务器帐号 * @param string
数据库服务器密码 * @param string
数据库名 * @param bool
是否保持持续连接,
1
为持续连接,
0
为非持续连接 * @return link_identifier */ function connect($dbhost, $dbuser, $dbpw, $dbname, $pconnect = 0) { global $CONFIG; $func = $pconnect == 1 ? 'mysql_pconnect' : 'mysql_connect'; /** mysql_pconnect()
为常连接。它和
mysql_connect
的区别是 前者在多进程的
WEB
服务器上效率比较好。但也有瑕疵就是在有关事务和数据表锁方面。详情请查看自己的手册。 */ if(!$this->connid = @$func($dbhost, $dbuser, $dbpw)) { $this->halt('Can not connect to MySQL server'); } //
当
mysql
版本为
4.1
以上时,启用数据库字符集设置 if($this->version() > '4.1' && $CONFIG['dbcharset']) { mysql_query("SET NAMES '".$CONFIG['dbcharset']."'" , $this->connid); } //
当
mysql
版本为
5.0
以上时,设置
sql mode,mysql5
数据库带了字符集模式。设置下就好 if($this->version() > '5.0') { mysql_query("SET sql_mode=''" , $this->connid); } if($dbname) { if([email=!@mysql_select_db($dbname]!@mysql_select_db($dbname[/email] , $this->connid)) { $this->halt('Cannot use database '.$dbname); } } return $this->connid; } /** *
选择数据库 * @param string
数据库名 */ function select_db($dbname) { return mysql_select_db($dbname , $this->connid); } /** *
执行
sql
语句 * @param string sql
语句 * @param string
默认为空,可选值为
CACHE UNBUFFERED * @param int Cache
以秒为单位的生命周期 * @return resource */ function query($sql , $type = '' , $expires = 3600, $dbname = '') { $func = $type == 'UNBUFFERED' ? 'mysql_unbuffered_query' : 'mysql_query'; /** mysql_unbuffered_query
效率更好。节省内存 看手册 */ if(!($query = $func($sql , $this->connid)) && $type != 'SILENT') { $this->halt('MySQL Query Error', $sql); } $this->querynum++; return $query; } /** *
执行
sql
语句,只得到一条记录 * @param string sql
语句 * @param string
默认为空,可选值为
CACHE UNBUFFERED * @param int Cache
以秒为单位的生命周期 * @return array */ function get_one($sql, $type = '', $expires = 3600, $dbname = '') { $query = $this->query($sql, $type, $expires, $dbname); $rs = $this->fetch_array($query); $this->free_result($query); return $rs ; } /** *
从结果集中取得一行作为关联数组 * @param resource
数据库查询结果资源 * @param string
定义返回类型 * @return array */ function fetch_array($query, $result_type = MYSQL_ASSOC) { return mysql_fetch_array($query, $result_type); } /** *
取得前一次
MySQL
操作所影响的记录行数 * @return int */ function affected_rows() { return mysql_affected_rows($this->connid); } /** *
取得结果集中行的数目 * @return int */ function num_rows($query) { return mysql_num_rows($query); } /** *
返回结果集中字段的数目 * @return int */ function num_fields($query) { return mysql_num_fields($query); } /** * @return array */ function result($query, $row) { return @mysql_result($query, $row); } function free_result($query) { return mysql_free_result($query); } /** *
取得上一步
INSERT
操作产生的
ID * @return int */ function insert_id() { return mysql_insert_id($this->connid); } /** * @return array */ function fetch_row($query) { return mysql_fetch_row($query); } /** * @return string */ function version() { return mysql_get_server_info($this->connid); } function close() { return mysql_close($this->connid); } /** * @return string */ function error() { return @mysql_error($this->connid); } /** * @return int */ function errno() { return intval(@mysql_errno($this->connid)) ; } /** mysql_errno()
函数也挺好使的哦。自己试下 */ /** *
显示
mysql
错误信息 */ function halt($message = '', $sql = '') { exit("MySQL Query:$sql <br> MySQL Error:".$this->error()." <br> MySQL Errno:".$this->errno()." <br> Message:$message"); } } ?> [url=http://bbs.phpcms.cn/misc.php?action=viewratings&tid=49276&pid=241974][/url] PHPCMS
的文本缓存实现 PHPCMS
的文本缓存实现
:
[Copy to clipboard]
[ - ] CODE: <?php defined('IN_PHPCMS') or exit('Access Denied'); /** 这个文件里面全是有关生成文本缓存的函数。文本缓存是个好东西。一般的项目,我们用不着内存缓存 :
memcached
,文本搞定。 原理是这样的: 我们在后台是不是可以设置很多有关网站的参数。而这些参数很多都是固定的。就不变化的。都存到咱的数据库上。而我们程序那里呢 每次都要访问数据库读出参数来进行我们程序中的操作。首先数据库查询是个很耗硬盘
IO
资源的一个东西,所以文本缓存刚好能减轻数据库那边的承重。 我们在程序开始就把数据库里面的配置都转化为数组 等
放到
php
文件里面。这样我们可以直接访问
php
文件而不用每次都访问数据库了。
php
文本缓存其实成了 我们程序和数据库的一个中间件。 所以我们自己写自己的文本缓存的时候其实要实现的很简单:
读数据库
->
写到
PHP
文件
->
程序中
include 来吧。开始文本缓存学习 */ function cache_all() //
生成所有缓存的总操作函数 { cache_table(); //
生成所有的数据库表名
,
表名是根据数据库里面当前的表明而生成。请看这个函数的详细分析 require_once PHPCMS_CACHEDIR.'table.php'; //
包含表常量 cache_common(); cache_member_group(); $modules = cache_module(); $channelids = cache_channel(0); $keyids = array_merge($modules, $channelids); foreach($keyids as $keyid) { $catids = cache_categorys($keyid); if(is_array($catids)) { foreach($catids as $catid) { cache_category($catid); } } } cache_type(0); return TRUE; } function cache_common() { global $db; $query = $db->query("SELECT module,name,iscore,iscopy,isshare,moduledir,moduledomain FROM ".TABLE_MODULE." WHERE disabled=0"); //
查询所有能用的模块 while($r = $db->fetch_array($query)) { $r['linkurl'] = ''; if($r['module'] != 'phpcms' && $r['iscopy'] == 0) $r['linkurl'] = linkurl($r['moduledomain'] ? dir_path($r['moduledomain']) : $r['moduledir'].'/'); //
如果模块存在目录的就取它目录地址 unset($r['moduledomain']); $key = $r['module']; $data[$key] = $r; } $CACHE['module'] = $data; //
存到缓存数组,等一下一起把
$CACHE
数组写到文本里去 $data = array(); $query = $db->query("SELECT channelid,module,channelname,channeldir,channeldomain,channelpic,introduce,style,islink,linkurl,cat_html_urlruleid,item_html_urlruleid,special_html_urlruleid,cat_php_urlruleid,item_php_urlruleid,special_php_urlruleid FROM ".TABLE_CHANNEL." WHERE disabled=0 ORDER by listorder"); //
罗列能用的频道列表 while($r = $db->fetch_array($query)) { $r['linkurl'] = linkurl($r['linkurl']); $key = $r['channelid']; $data[$key] = $r; } $CACHE['channel'] = $data; //
存到缓存数组 $data = array(); $r = $db->get_one("SELECT setting FROM ".TABLE_MODULE." WHERE module='phpcms'"); $CACHE['phpcms'] = unserialize($r['setting']); //
查询
phpcms
这个模块的设置信息,大家可以看下数据库这个表内容。
setting
字段里面的信息是经过
serialize
函数窜行化的。 //
所以取出的内容要
unserialize
反窜行
.
我是挺喜欢使用
serialize
函数的。他可以实现把一个数组存到数据库或把一个对象存到数据库。或是拿来
GET
传递都行。 //
太强了。大家可以试用下。可能你项目某个地方需要用到哦。 $fields = array(); $result = $db->query("SELECT * FROM ".TABLE_FIELD." ORDER BY fieldid"); //
下栽模块的信息,请自己看下这个表的数据就明白 while($r = $db->fetch_array($result)) { $tablename = $r['tablename']; $fields[$tablename] .= ','.$r['name']; } $CACHE['field'] = $fields; cache_write('common.php', $CACHE); //
开始把
$CACHE
数组写到
common.php
这个文本缓存里。大家可以自己去打开这个文件看下内容。一切了然 return $CACHE; } function cache_update($action='')//
更新文本缓存。最好在后台操作使用。因为
PHP
的文件
flock
文件锁在某些平台使用不是很好。会出现多用户同写一个文件从而破坏缓存文件 { global $db; $data=array(); switch($action) { case 'keylink'; $query=$db->query("SELECT linktext,linkurl FROM ".TABLE_KEYLINK." where passed=1"); while($r=$db->fetch_array($query)){ $data[]=$r; } break; case 'reword'; $query = $db->query("SELECT word,replacement FROM ".TABLE_REWORD." where passed=1"); while($r = $db->fetch_array($query)) { $data[]=$r; } break; default: $actions = array('keylink','reword'); array_map('cache_update', $actions); return TRUE; } cache_write('cache_'.$action.'.php', $data); return $data; } function cache_table() { global $db,$CONFIG; $query = $db->query("SHOW TABLES FROM `".$CONFIG['dbname']."`"); /** 显示数据库里面的所有表名 */ while($r = $db->fetch_row($query)) { $table = $r[0]; if(preg_match("/^".$CONFIG['tablepre']."/i", $table)) //
寻找表前缀等于
$CONFIG['tablepre'] (
在
config.inc.php
里设置
) @@
表前缀还有这个作用 嘿嘿 { $tablename = str_replace($CONFIG['tablepre'], 'table_', $table); $data[$tablename] = $table; // $data['table_xx'] = xx;
形式
只能意会下了 } } $db->free_result($query); //$db->free_result()
这个类方法其实是掉用了函数:
mysql_free_result()
函数 主要是为了清除数据库大的查询而占用的内存。还是有必要的哦 if(!is_dir(PHPCMS_CACHEDIR)) //
常量
PHPCMS_CACHEDIR
在
common.inc.php
里面定义的。大家不记得了去看看吧。是存放
phpcms
缓存目录的路径,这里意思是:如果缓存目录不存在 { dir_create(PHPCMS_CACHEDIR); //
如果缓存目录不存在那么就创建 dir_create($CONFIG['templatescachedir']); //
创建编译后的
PHP
模板目录,有关
phpcms
模板引擎编写。在下一章合适就开讲 /** dir_create()
函数为创建 目录函数。
PHPCMS
自己封装的,刚看了下。
phpcms
挺强。这个函数还可以通过
ftp
来创建目录。这样就可以解决一些 开启了安全模式下的服务器对于创建目录等出现的问题
因为涉及到
PHP FTP
知识。所以打算讲解到下面再说。 */ } cache_write('table.php', $data , 'constant'); //
很多朋友说找不到
phpcms
表常量在那里定义的。就是在这里。 /** cache_write()
函数在
global.func.php
里面定义的。是把 已经从数据库取出来的数组信息写到
PHP
文本上去。
@@
文本缓存关键的一步
废话少说上菜: function cache_write($file, $string, $type = 'array') { if(is_array($string)) //
检测
$string
内容是字符窜的呢还是数组的,是数组的那就继续
.. { $type = strtolower($type); if($type == 'array')//
然后再判断这个函数的模式标致 ,是否为数组模式
,
默认为数组模式 { $string = "<?php\n return ".var_export($string,TRUE).";\n?>"; //
这个太关键了。因为我们把数据库的信息写到文本上去的时候。是以符合
PHP
语法的格式写进去的。为什么呢?
@@
十分废话,因为如果不是以
PHP
格式写到文件里面去
那么这个
PHP
文件怎么能给我们
include
进程序运行调用呢? 呵呵。 知道这一点就真的明白文本缓存的实现了。忒简单。 这里使用了个小技巧:使用了
var_export()
函数
这个函数会返回一个变量的字符窜形式。这个函数太有帮助了。如果没有这个函数,我们还要自己想办法实现呢。自己写一次文本缓存就明白了。会碰到这个问题的。
'\n'
这个是
文本文件的换行。初学者 别把
<br>
和
'\n'
搞混罗。 一个是
html
的 一个是文本文件的 } elseif($type == 'constant') //
以内容形式 { $data=''; foreach($string as $key => $value) $data .= "define('".strtoupper($key)."','".addslashes($value)."');\n"; $string = "<?php\n".$data."\n?>";
如果以内容形式的话。就不是写数组到文本里面了。而是把内容都定义成常量。 } } $strlen = file_put_contents(PHPCMS_CACHEDIR.$file, $string);//file_put_contents()
函数 是
PHP5
才支持的 效率最好。建议使用 chmod(PHPCMS_CACHEDIR.$file, 0777);
设置目录 为可读可写可执行 return $strlen; //
返回写到文本的字节数 }
再说多一个读 缓存文件的操作函数
:上菜 function cache_read($file, $mode = 'i') { $cachefile = PHPCMS_CACHEDIR.$file; if(!file_exists($cachefile)) return array(); return $mode == 'i' ? include $cachefile : file_get_contents($cachefile); }
读缓存其实就是
include php
缓存文件。 讲完走人 */ return $data; } /** phpcms
的所有数据库表名 都用根据数据库当前的表名来用常量来进行定义。我认为这样设计不是很好。不够灵活:比如如果我们更改数据库的一个表名的话。 那么会出现找不到表的错误信息。而且想要修复还很麻烦。就是说不能随便更改表名了。不推荐大家这样写。我们可以把表名都定义在一个
PHP
文件里面。这样我们以后 要改某个表名,就很方便了。 */ PHPCMS
整站代码分析讲解(四)续
[Copy to clipboard]
[ - ] CODE: function cache_module($module = '') { global $db; if($module) { $r = $db->get_one("SELECT setting,module,name,iscopy,moduledir,moduledomain FROM ".TABLE_MODULE." WHERE module='$module'"); //
模块具体信息 if($r['setting']) { $setting = unserialize($r['setting']); //
讲过了反窜行。因为里面信息是窜行化后再存到数据库的 } $setting['name'] = $r['name']; $setting['moduledir'] = $r['moduledir']; $setting['moduledomain'] = $r['moduledomain']; $setting['linkurl'] = ''; if($r['module'] != 'phpcms' && $r['iscopy'] == 0) { $setting['linkurl'] = linkurl($r['moduledomain'] ? dir_path($r['moduledomain']) : $r['moduledir'].'/'); cache_categorys($module); } unset($r['moduledomain']); cache_write($module.'_setting.php', $setting); return $setting; } else { $query = $db->query("SELECT module FROM ".TABLE_MODULE." WHERE disabled=0 ORDER by moduleid"); while($r = $db->fetch_array($query)) { cache_module($r['module']); $modules[] = $r['module']; } return $modules; } } function cache_channel($channelid=0) { global $db; if($channelid) { $data = $db->get_one("SELECT * FROM ".TABLE_CHANNEL." WHERE channelid=$channelid"); if($data && !$data['islink']) { if($data['setting']) { $setting = unserialize($data['setting']); unset($data['setting']); $data = is_array($setting) ? array_merge($data, $setting) : $data; } $data['linkurl'] = linkurl($data['linkurl']); cache_write('channel_'.$channelid.'.php', $data); cache_categorys($channelid); return $data; } } else { $query = $db->query("SELECT channelid FROM ".TABLE_CHANNEL." WHERE islink=0 AND disabled=0 ORDER by channelid"); while($r = $db->fetch_array($query)) { cache_channel($r['channelid']); $channelids[] = $r['channelid']; } return $channelids; } } function cache_categorys($keyid) { global $db,$PHPCMS,$CHANNEL; $urlpre = ''; if(is_numeric($keyid)) { $keyid = intval($keyid); $module = $CHANNEL[$keyid]['module']; $sql = " channelid=$keyid "; } else { $sql = " module='$keyid' "; } $catids = $data = array(); $query = $db->query("SELECT module,channelid,catid,catname,style,introduce,catpic,islink,catdir,linkurl,parentid,arrparentid,parentdir,child,arrchildid,items,itemordertype,itemtarget,ismenu,islist,ishtml,htmldir,prefix,urlruleid,item_prefix,item_html_urlruleid,item_php_urlruleid FROM ".TABLE_CATEGORY." WHERE $sql ORDER by listorder,catid"); while($r = $db->fetch_array($query)) { $r['linkurl'] = str_replace($PHPCMS['index'].'.'.$PHPCMS['fileext'], '', $r['linkurl']); $r['linkurl'] = $urlpre ? preg_replace("|^".$urlpre."|", '', $r['linkurl']) : linkurl($r['linkurl']); $catid = $r['catid']; $data[$catid] = $r; $catids[] = $catid; } if($data) cache_write('categorys_'.$keyid.'.php', $data); //
写缓存罗。 return $catids; } function cache_category($catid) { global $db,$PHPCMS; if(!$catid) return FALSE; $data = $db->get_one("SELECT * FROM ".TABLE_CATEGORY." WHERE catid=$catid"); $setting = unserialize($data['setting']); unset($data['setting']); $data = is_array($setting) ? array_merge($data, $setting) : $data; $data['linkurl'] = linkurl(str_replace($PHPCMS['index'].'.'.$PHPCMS['fileext'], '', $data['linkurl'])); cache_write('category_'.$catid.'.php', $data); return $data; } function cache_type($keyid=0) { global $db; if($keyid) { $result = $db->query("SELECT * FROM ".TABLE_TYPE." WHERE keyid='$keyid'"); $data = array(); while($r = $db->fetch_array($result)) { $r['introduce'] = $r['introduce']? $r['introduce']:' '; $data[$r['typeid']] = $r; } if($data) { cache_write('type_'.$keyid.'.php', $data); } return $data; } else { $modules = array(); $query = $db->query("SELECT module FROM ".TABLE_MODULE." WHERE disabled=0 ORDER by moduleid"); while($r = $db->fetch_array($query)) { $modules[] = $r['module']; } $channelids = array(); $query = $db->query("SELECT channelid FROM ".TABLE_CHANNEL." WHERE islink=0 AND disabled=0 ORDER by channelid"); while($r = $db->fetch_array($query)) { $channelids[] = $r['channelid']; } $modulechannels = array_merge($modules,$channelids); foreach($modulechannels as $m) { $result = $db->query("SELECT * FROM ".TABLE_TYPE." WHERE keyid='$m'"); $TYPE = array(); while($r = $db->fetch_array($result)) { $r['introduce'] = $r['introduce']? $r['introduce']:' '; $TYPE[$r['typeid']] = $r; } cache_write('type_'.$m.'.php',$TYPE); } return $modulechannels; } } function cache_member_group() { global $db; $query = $db->query("SELECT * FROM ".TABLE_MEMBER_GROUP." ORDER BY groupid"); //
用户组信息 while($r = $db->fetch_array($query)) { $groupid = $r['groupid']; cache_write('member_group_'.$groupid.'.php', $r); $data[$groupid] = $r; } cache_write('member_group.php', $data); //
明白了吧。写缓存罗 return $data; } function cache_banip() { global $db,$PHP_TIME; $result = $db->query("SELECT ip,overtime FROM ".TABLE_BANIP." WHERE ifban=1 and overtime>=$PHP_TIME order by id desc "); while($r = $db->fetch_array($result)) { $data[] = array('ip'=>$r['ip'],'overtime'=>$r['overtime']); } $db->free_result($result); cache_write('banip.php', $data); return $data; } ?>
转载于:https://www.cnblogs.com/gxldan/archive/2011/10/26/4066764.html