phpcms 源码分析五:文件缓存实现
2013-09-29 12:52
453 查看
这次是逆雪寒的文件缓存实现代码分析:
/* [/php] PHPCMS的文本缓存实现: [php] <?php /* 这个文件里面全是有关生成文本缓存的函数。文本缓存是个好东西。一般的项目,我们用不着内存缓存 : memcached ,文本搞定。 原理是这样的: 我们在后台是不是可以设置很多有关网站的参数。而这些参数很多都是固定的。就不变化的。都存到咱的数据库上。而我们程序那里呢 每次都要访问数据库读出参数来进行我们程序中的操作。首先数据库查询是个很耗硬盘IO资源的一个东西,所以文本缓存刚好能减轻数据库那边的承重。 我们在程序开始就把数据库里面的配置都转化为数组 等 放到 php文件里面。这样我们可以直接访问php文件而不用每次都访问数据库了。 php文本缓存其实成了我们程序和数据库的一个中间件。 所以我们自己写自己的文本缓存的时候其实要实现的很简单: 读数据库 -> 写到PHP文件 -> 程序中include ;来吧。开始文本缓存学习 */ defined('IN_PHPCMS') or exit('Access Denied'); // 生成所有缓存的总操作函数 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 数组写到文本里去 $CACHE['module'] = $data; $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(); // 查询 phpcms这个模块的设置信息,大家可以看下数据库这个表内容。setting 字段里面的信息是经过serialize 函数串行化的 $r = $db->get_one("SELECT setting FROM ".TABLE_MODULE." WHERE module='phpcms'"); /* * 所以取出的内容要unserialize 反串行.我是挺喜欢使用serialize 函数的。 * 他可以实现把一个数组存到数据库或把一个对象存到数据库。或是拿来GET传递都行。 * 太强了。大家可以试用下。可能你项目某个地方需要用到哦。 */ $CACHE['phpcms'] = unserialize($r['setting']); $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 数组写到 common.php 这个文本缓存里。大家可以自己去打开这个文件看下内容。一切了然 cache_write('common.php', $CACHE); return $CACHE; } // 更新文本缓存。最好在后台操作使用。因为PHP的文件flock 文件锁在某些平台使用不是很好。会出现多用户同写一个文件从而破坏缓存文件 function cache_update($action = '') { 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]; // 寻找表前缀等于 $CONFIG['tablepre'] (在config.inc.php里设置) @@表前缀还有这个作用 嘿嘿 if(preg_match("/^".$CONFIG['tablepre']."/i", $table)) { $tablename = str_replace($CONFIG['tablepre'], 'table_', $table); // $data['table_xx'] = xx; 形式 只能意会下了 $data[$tablename] = $table; } } // $db->free_result() 这个类方法其实是调用了函数:mysql_free_result() 函数 // 主要是为了清除数据库大量的查询而占用的内存。还是有必要的哦 $db->free_result($query); // 常量 PHPCMS_CACHEDIR 在 common.inc.php 里面定义的。大家不记得了去看看吧。 // 是存放phpcms 缓存目录的路径,这里意思是:如果缓存目录不存在 if(!is_dir(PHPCMS_CACHEDIR)) { // 如果缓存目录不存在那么就创建 dir_create(PHPCMS_CACHEDIR); // 创建编译后的PHP模板目录,有关phpcms模板引擎编写。在下一章合适就开讲 dir_create($CONFIG['templatescachedir']); /* dir_create() 函数为创建 目录函数。PHPCMS自己封装的,刚看了下。phpcms 挺强。 这个函数还可以通过ftp 来创建目录。这样就可以解决一些 开启了安全模式下的服务器对于创建目录等出现的问题 因为涉及到PHP FTP 知识。所以打算讲解到下面再说。 */ } /* cache_write() 函数在global.func.php里面定义的。是把 已经从数据库取出来的数组信息写到 PHP文本上去。 @@文本缓存关键的一步 废话少说上菜: */ cache_write('table.php', $data , 'constant'); //很多朋友说找不到phpcms 表常量在那里定义的。就是在这里。 function cache_write($file, $string, $type = 'array') { // 检测 $string 内容是字符串的呢还是数组的,是数组的那就继续 .. if(is_array($string)) { $type = strtolower($type); // 然后再判断这个函数的模式标志 ,是否为数组模式,默认为数组模式 if($type == 'array') { /*这个太关键了。因为我们把数据库的信息写到文本上去的时候。是以符合PHP语法的格式写进去的。为什么呢?@@ * 十分废话,因为如果不是以PHP格式写到文件里面去,那么这个PHP文件怎么能给我们include 进程序运行调用呢? * 呵呵。 知道这一点就真的明白文本缓存的实现了。忒简单。 这里使用了个小技巧:使用了 var_export() 函数 * 这个函数会返回一个变量的字符串形式。这个函数太有帮助了。如果没有这个函数,我们还要自己想办法实现呢。 * 自己写一次文本缓存就明白了。会碰到这个问题的。 '\n' 这个是文本文件的换行。初学者 别把<br> 和 '\n' 搞混罗。 * 一个是html 的 一个是文本文件的。 */ $string = "<?php\n return ".var_export($string,TRUE).";\n?>"; } // 以内容形式 elseif($type == 'constant') { $data=''; foreach($string as $key => $value) $data .= "define('".strtoupper($key)."','".addslashes($value)."');\n"; // 如果以内容形式的话。就不是写数组到文本里面了。而是把内容都定义成常量。 $string = "<?php\n".$data."\n?>"; } } // file_put_contents()函数 是PHP5才支持的 效率最好。建议使用 $strlen = file_put_contents(PHPCMS_CACHEDIR.$file, $string); // 设置目录 为可读可写可执行 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文件里面。 这样我们以后要改某个表名,就很方便了。 */ 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; }
相关文章推荐
- phpcms 源码分析六:index文件
- cocos2d-x3.2源码分析(一)类FileUtils--实现把资源放在Resources文件目录下达到多平台的引用
- phpcms 源码分析七: 模板引擎实现
- 【Cocos2d-x 3.2源码分析】(一)类FileUtils -- 实现把资源放在Resources文件目录下达到多平台的引用
- 【Python】实现网站备份文件扫描+源码分析
- [转载]cocos2d-x3.2源码分析(一)类FileUtils--实现把资源放在Resources文件目录下达到多平台的引用
- 【Android】源码分析 - LRUCache缓存实现原理
- cocos2d-x3.2源码分析之 ---- 类FileUtils实现把资源放在Resources文件目录下达到多平台的引用
- 【phpcms-v9】cache_all.php文件分析-更新缓存
- jQuery缓存实现的分析-及源码解读
- Java并发框架Disruptor实现原理与源码分析(二) 缓存行填充与CAS操作
- cocos2d-x3.2源码分析(一)类FileUtils--实现把资源放在Resources文件目录下达到多平台的引用
- Okhttp缓存源码分析以及自定义缓存实现
- [Android源码分析]蓝牙文件传输过程解析之UI实现
- ABP源码分析十三:缓存Cache实现
- 【phpcms-v9】cache_all.php文件分析-更新缓存
- 蔡军生先生第二人生的源码分析(六十二)类Easy实现多协议文件传送
- Hhadoop-2.7.0中HDFS写文件源码分析(二):客户端实现(1)
- phpcms 源码分析四: 数据库类实现
- 第二人生的源码分析(六十二)类Easy实现多协议文件传送