PHPCMS的文本缓存实现
CODE:
1
<?
php
2 defined ( ' IN_PHPCMS ' ) or exit ( ' Access Denied ' );
3 /* *
4 这个文件里面全是有关生成文本缓存的函数。文本缓存是个好东西。一般的项目,我们用不着内存缓存 : memcached ,文本搞定。
5 原理是这样的: 我们在后台是不是可以设置很多有关网站的参数。而这些参数很多都是固定的。就不变化的。都存到咱的数据库上。而我们程序那里呢
6 每次都要访问数据库读出参数来进行我们程序中的操作。首先数据库查询是个很耗硬盘IO资源的一个东西,所以文本缓存刚好能减轻数据库那边的承重。
7 我们在程序开始就把数据库里面的配置都转化为数组 等 放到 php文件里面。这样我们可以直接访问php文件而不用每次都访问数据库了。 php文本缓存其实成了
8 我们程序和数据库的一个中间件。 所以我们自己写自己的文本缓存的时候其实要实现的很简单: 读数据库 -> 写到PHP文件 -> 程序中include
9 来吧。开始文本缓存学习
10 */
11 function cache_all() // 生成所有缓存的总操作函数
12 {
13 cache_table(); // 生成所有的数据库表名,表名是根据数据库里面当前的表明而生成。请看这个函数的详细分析
14 require_once PHPCMS_CACHEDIR . ' table.php ' ; // 包含表常量
15 cache_common();
16 cache_member_group();
17 $modules = cache_module();
18 $channelids = cache_channel( 0 );
19 $keyids = array_merge ( $modules , $channelids );
20 foreach ( $keyids as $keyid )
21 {
22 $catids = cache_categorys( $keyid );
23 if ( is_array ( $catids ))
24 {
25 foreach ( $catids as $catid )
26 {
27 cache_category( $catid );
28 }
29 }
30 }
31 cache_type( 0 );
32 return TRUE ;
33 }
34 function cache_common()
35 {
36 global $db ;
37 $query = $db -> query( " SELECT module,name,iscore,iscopy,isshare,moduledir,moduledomain FROM " . TABLE_MODULE . " WHERE disabled=0 " ); // 查询所有能用的模块
38 while ( $r = $db -> fetch_array( $query ))
39 {
40 $r [ ' linkurl ' ] = '' ;
41 if ( $r [ ' module ' ] != ' phpcms ' && $r [ ' iscopy ' ] == 0 ) $r [ ' linkurl ' ] = linkurl( $r [ ' moduledomain ' ] ? dir_path( $r [ ' moduledomain ' ]) : $r [ ' moduledir ' ] . ' / ' );
42 // 如果模块存在目录的就取它目录地址
43 unset ( $r [ ' moduledomain ' ]);
44 $key = $r [ ' module ' ];
45 $data [ $key ] = $r ;
46 }
47 $CACHE [ ' module ' ] = $data ; // 存到缓存数组,等一下一起把 $CACHE 数组写到文本里去
48 $data = array ();
49 $query = $db -> query( " SELECT channelid,module,channelname,channeldir,channeldomain,channelpic,introduce,
50 style,islink,linkurl,cat_html_urlruleid,item_html_urlruleid,special_html_urlruleid,
51 cat_php_urlruleid,item_php_urlruleid,special_php_urlruleid FROM " . TABLE_CHANNEL . " WHERE disabled=0 ORDER by listorder " ); // 罗列能用的频道列表
52 while ( $r = $db -> fetch_array( $query ))
53 {
54 $r [ ' linkurl ' ] = linkurl( $r [ ' linkurl ' ]);
55 $key = $r [ ' channelid ' ];
56 $data [ $key ] = $r ;
57 }
58 $CACHE [ ' channel ' ] = $data ; // 存到缓存数组
59 $data = array ();
60 $r = $db -> get_one( " SELECT setting FROM " . TABLE_MODULE . " WHERE module='phpcms' " );
61 $CACHE [ ' phpcms ' ] = unserialize ( $r [ ' setting ' ]);
62 // 查询 phpcms这个模块的设置信息,大家可以看下数据库这个表内容。setting 字段里面的信息是经过serialize 函数窜行化的。
63 //所以取出的内容要unserialize 反窜行.我是挺喜欢使用serialize 函数的。他可以实现把一个数组存到数据库或把一个对象存到数据库。或是拿来GET传递都行。
64 //太强了。大家可以试用下。可能你项目某个地方需要用到哦。
65 $fields = array ();
66 $result = $db -> query( " SELECT * FROM " . TABLE_FIELD . " ORDER BY fieldid " ); // 下栽模块的信息,请自己看下这个表的数据就明白
67 while ( $r = $db -> fetch_array( $result ))
68 {
69 $tablename = $r [ ' tablename ' ];
70 $fields [ $tablename ] .= ' , ' . $r [ ' name ' ];
71 }
72 $CACHE [ ' field ' ] = $fields ;
73 cache_write( ' common.php ' , $CACHE ); // 开始把$CACHE 数组写到 common.php 这个文本缓存里。大家可以自己去打开这个文件看下内容。一切了然
74 return $CACHE ;
75 }
76 function cache_update( $action = '' ) // 更新文本缓存。最好在后台操作使用。因为PHP的文件flock 文件锁在某些平台使用不是很好。会出现多用户同写一个文件从而破坏缓存文件
77 {
78 global $db ;
79 $data = array ();
80 switch ( $action )
81 {
82 case ' keylink ' ;
83 $query = $db -> query( " SELECT linktext,linkurl FROM " . TABLE_KEYLINK . " where passed=1 " );
84 while ( $r = $db -> fetch_array( $query )){
85 $data [] = $r ;
86 }
87 break ;
88 case ' reword ' ;
89 $query = $db -> query( " SELECT word,replacement FROM " . TABLE_REWORD . " where passed=1 " );
90 while ( $r = $db -> fetch_array( $query ))
91 {
92 $data [] = $r ;
93 }
94 break ;
95 default :
96 $actions = array ( ' keylink ' , ' reword ' );
97 array_map ( ' cache_update ' , $actions );
98 return TRUE ;
99 }
100 cache_write( ' cache_ ' . $action . ' .php ' , $data );
101 return $data ;
102 }
103 function cache_table()
104 {
105 global $db , $CONFIG ;
106 $query = $db -> query( " SHOW TABLES FROM ` " . $CONFIG [ ' dbname ' ] . " ` " );
107 /* *
108 显示数据库里面的所有表名
109 */
110 while ( $r = $db -> fetch_row( $query ))
111 {
112 $table = $r [ 0 ];
113 if ( preg_match ( " /^ " . $CONFIG [ ' tablepre ' ] . " /i " , $table )) // 寻找表前缀等于 $CONFIG['tablepre'] (在config.inc.php里设置) @@表前缀还有这个作用 嘿嘿
114 {
115 $tablename = str_replace ( $CONFIG [ ' tablepre ' ] , ' table_ ' , $table );
116 $data [ $tablename ] = $table ; // $data['table_xx'] = xx; 形式 只能意会下了
117 }
118 }
119 $db -> free_result( $query ); // $db->free_result() 这个类方法其实是掉用了函数:mysql_free_result() 函数 主要是为了清除数据库大的查询而占用的内存。还是有必要的哦
120 if ( ! is_dir (PHPCMS_CACHEDIR)) // 常量 PHPCMS_CACHEDIR 在 common.inc.php 里面定义的。大家不记得了去看看吧。是存放phpcms 缓存目录的路径,这里意思是:如果缓存目录不存在
121 {
122 dir_create(PHPCMS_CACHEDIR); // 如果缓存目录不存在那么就创建
123 dir_create( $CONFIG [ ' templatescachedir ' ]); // 创建编译后的PHP模板目录,有关phpcms模板引擎编写。在下一章合适就开讲
124 /* *
125 dir_create() 函数为创建 目录函数。PHPCMS自己封装的,刚看了下。phpcms 挺强。这个函数还可以通过ftp 来创建目录。这样就可以解决一些 开启了安全模式下的服务器对于创建目录等出现的问题
126 因为涉及到PHP FTP 知识。所以打算讲解到下面再说。
127 */
128 }
129 cache_write( ' table.php ' , $data , ' constant ' ); // 很多朋友说找不到phpcms 表常量在那里定义的。就是在这里。
130 /* *
131 cache_write() 函数在global.func.php里面定义的。是把 已经从数据库取出来的数组信息写到 PHP文本上去。@@文本缓存关键的一步 废话少说上菜:
132 function cache_write($file, $string, $type = 'array')
133 {
134 if(is_array($string)) //检测 $string 内容是字符窜的呢还是数组的,是数组的那就继续 ..
135 {
136 $type = strtolower($type);
137 if($type == 'array')//然后再判断这个函数的模式标致 ,是否为数组模式,默认为数组模式
138 {
139 $string = "<?php"n return ".var_export($string,TRUE).";"n?>";
140 //这个太关键了。因为我们把数据库的信息写到文本上去的时候。是以符合PHP语法的格式写进去的。为什么呢?@@ 十分废话,因为如果不是以PHP格式写到文件里面去
141 那么这个PHP文件怎么能给我们include 进程序运行调用呢? 呵呵。 知道这一点就真的明白文本缓存的实现了。忒简单。 这里使用了个小技巧:使用了 var_export() 函数
142 这个函数会返回一个变量的字符窜形式。这个函数太有帮助了。如果没有这个函数,我们还要自己想办法实现呢。自己写一次文本缓存就明白了。会碰到这个问题的。 '"n' 这个是
143 文本文件的换行。初学者 别把<br> 和 '"n' 搞混罗。 一个是html 的 一个是文本文件的
144 }
145 elseif($type == 'constant') //以内容形式
146 {
147 $data='';
148 foreach($string as $key => $value) $data .= "define('".strtoupper($key)."','".addslashes($value)."');"n";
149 $string = "<?php"n".$data.""n?>";
150 如果以内容形式的话。就不是写数组到文本里面了。而是把内容都定义成常量。
151 }
152 }
153 $strlen = file_put_contents(PHPCMS_CACHEDIR.$file, $string);//file_put_contents()函数 是PHP5才支持的 效率最好。建议使用
154 chmod(PHPCMS_CACHEDIR.$file, 0777); 设置目录 为可读可写可执行
155 return $strlen; //返回写到文本的字节数
156 }
157
158 再说多一个读 缓存文件的操作函数 :上菜
159 function cache_read($file, $mode = 'i')
160 {
161 $cachefile = PHPCMS_CACHEDIR.$file;
162 if(!file_exists($cachefile)) return array();
163 return $mode == 'i' ? include $cachefile : file_get_contents($cachefile);
164 }
165 读缓存其实就是 include php缓存文件。 讲完走人
166 */
167 return $data ;
168 }
169 /* *
170 phpcms 的所有数据库表名 都用根据数据库当前的表名来用常量来进行定义。我认为这样设计不是很好。不够灵活:比如如果我们更改数据库的一个表名的话。
171 那么会出现找不到表的错误信息。而且想要修复还很麻烦。就是说不能随便更改表名了。不推荐大家这样写。我们可以把表名都定义在一个PHP文件里面。这样我们以后
172 要改某个表名,就很方便了。
173 */
2 defined ( ' IN_PHPCMS ' ) or exit ( ' Access Denied ' );
3 /* *
4 这个文件里面全是有关生成文本缓存的函数。文本缓存是个好东西。一般的项目,我们用不着内存缓存 : memcached ,文本搞定。
5 原理是这样的: 我们在后台是不是可以设置很多有关网站的参数。而这些参数很多都是固定的。就不变化的。都存到咱的数据库上。而我们程序那里呢
6 每次都要访问数据库读出参数来进行我们程序中的操作。首先数据库查询是个很耗硬盘IO资源的一个东西,所以文本缓存刚好能减轻数据库那边的承重。
7 我们在程序开始就把数据库里面的配置都转化为数组 等 放到 php文件里面。这样我们可以直接访问php文件而不用每次都访问数据库了。 php文本缓存其实成了
8 我们程序和数据库的一个中间件。 所以我们自己写自己的文本缓存的时候其实要实现的很简单: 读数据库 -> 写到PHP文件 -> 程序中include
9 来吧。开始文本缓存学习
10 */
11 function cache_all() // 生成所有缓存的总操作函数
12 {
13 cache_table(); // 生成所有的数据库表名,表名是根据数据库里面当前的表明而生成。请看这个函数的详细分析
14 require_once PHPCMS_CACHEDIR . ' table.php ' ; // 包含表常量
15 cache_common();
16 cache_member_group();
17 $modules = cache_module();
18 $channelids = cache_channel( 0 );
19 $keyids = array_merge ( $modules , $channelids );
20 foreach ( $keyids as $keyid )
21 {
22 $catids = cache_categorys( $keyid );
23 if ( is_array ( $catids ))
24 {
25 foreach ( $catids as $catid )
26 {
27 cache_category( $catid );
28 }
29 }
30 }
31 cache_type( 0 );
32 return TRUE ;
33 }
34 function cache_common()
35 {
36 global $db ;
37 $query = $db -> query( " SELECT module,name,iscore,iscopy,isshare,moduledir,moduledomain FROM " . TABLE_MODULE . " WHERE disabled=0 " ); // 查询所有能用的模块
38 while ( $r = $db -> fetch_array( $query ))
39 {
40 $r [ ' linkurl ' ] = '' ;
41 if ( $r [ ' module ' ] != ' phpcms ' && $r [ ' iscopy ' ] == 0 ) $r [ ' linkurl ' ] = linkurl( $r [ ' moduledomain ' ] ? dir_path( $r [ ' moduledomain ' ]) : $r [ ' moduledir ' ] . ' / ' );
42 // 如果模块存在目录的就取它目录地址
43 unset ( $r [ ' moduledomain ' ]);
44 $key = $r [ ' module ' ];
45 $data [ $key ] = $r ;
46 }
47 $CACHE [ ' module ' ] = $data ; // 存到缓存数组,等一下一起把 $CACHE 数组写到文本里去
48 $data = array ();
49 $query = $db -> query( " SELECT channelid,module,channelname,channeldir,channeldomain,channelpic,introduce,
50 style,islink,linkurl,cat_html_urlruleid,item_html_urlruleid,special_html_urlruleid,
51 cat_php_urlruleid,item_php_urlruleid,special_php_urlruleid FROM " . TABLE_CHANNEL . " WHERE disabled=0 ORDER by listorder " ); // 罗列能用的频道列表
52 while ( $r = $db -> fetch_array( $query ))
53 {
54 $r [ ' linkurl ' ] = linkurl( $r [ ' linkurl ' ]);
55 $key = $r [ ' channelid ' ];
56 $data [ $key ] = $r ;
57 }
58 $CACHE [ ' channel ' ] = $data ; // 存到缓存数组
59 $data = array ();
60 $r = $db -> get_one( " SELECT setting FROM " . TABLE_MODULE . " WHERE module='phpcms' " );
61 $CACHE [ ' phpcms ' ] = unserialize ( $r [ ' setting ' ]);
62 // 查询 phpcms这个模块的设置信息,大家可以看下数据库这个表内容。setting 字段里面的信息是经过serialize 函数窜行化的。
63 //所以取出的内容要unserialize 反窜行.我是挺喜欢使用serialize 函数的。他可以实现把一个数组存到数据库或把一个对象存到数据库。或是拿来GET传递都行。
64 //太强了。大家可以试用下。可能你项目某个地方需要用到哦。
65 $fields = array ();
66 $result = $db -> query( " SELECT * FROM " . TABLE_FIELD . " ORDER BY fieldid " ); // 下栽模块的信息,请自己看下这个表的数据就明白
67 while ( $r = $db -> fetch_array( $result ))
68 {
69 $tablename = $r [ ' tablename ' ];
70 $fields [ $tablename ] .= ' , ' . $r [ ' name ' ];
71 }
72 $CACHE [ ' field ' ] = $fields ;
73 cache_write( ' common.php ' , $CACHE ); // 开始把$CACHE 数组写到 common.php 这个文本缓存里。大家可以自己去打开这个文件看下内容。一切了然
74 return $CACHE ;
75 }
76 function cache_update( $action = '' ) // 更新文本缓存。最好在后台操作使用。因为PHP的文件flock 文件锁在某些平台使用不是很好。会出现多用户同写一个文件从而破坏缓存文件
77 {
78 global $db ;
79 $data = array ();
80 switch ( $action )
81 {
82 case ' keylink ' ;
83 $query = $db -> query( " SELECT linktext,linkurl FROM " . TABLE_KEYLINK . " where passed=1 " );
84 while ( $r = $db -> fetch_array( $query )){
85 $data [] = $r ;
86 }
87 break ;
88 case ' reword ' ;
89 $query = $db -> query( " SELECT word,replacement FROM " . TABLE_REWORD . " where passed=1 " );
90 while ( $r = $db -> fetch_array( $query ))
91 {
92 $data [] = $r ;
93 }
94 break ;
95 default :
96 $actions = array ( ' keylink ' , ' reword ' );
97 array_map ( ' cache_update ' , $actions );
98 return TRUE ;
99 }
100 cache_write( ' cache_ ' . $action . ' .php ' , $data );
101 return $data ;
102 }
103 function cache_table()
104 {
105 global $db , $CONFIG ;
106 $query = $db -> query( " SHOW TABLES FROM ` " . $CONFIG [ ' dbname ' ] . " ` " );
107 /* *
108 显示数据库里面的所有表名
109 */
110 while ( $r = $db -> fetch_row( $query ))
111 {
112 $table = $r [ 0 ];
113 if ( preg_match ( " /^ " . $CONFIG [ ' tablepre ' ] . " /i " , $table )) // 寻找表前缀等于 $CONFIG['tablepre'] (在config.inc.php里设置) @@表前缀还有这个作用 嘿嘿
114 {
115 $tablename = str_replace ( $CONFIG [ ' tablepre ' ] , ' table_ ' , $table );
116 $data [ $tablename ] = $table ; // $data['table_xx'] = xx; 形式 只能意会下了
117 }
118 }
119 $db -> free_result( $query ); // $db->free_result() 这个类方法其实是掉用了函数:mysql_free_result() 函数 主要是为了清除数据库大的查询而占用的内存。还是有必要的哦
120 if ( ! is_dir (PHPCMS_CACHEDIR)) // 常量 PHPCMS_CACHEDIR 在 common.inc.php 里面定义的。大家不记得了去看看吧。是存放phpcms 缓存目录的路径,这里意思是:如果缓存目录不存在
121 {
122 dir_create(PHPCMS_CACHEDIR); // 如果缓存目录不存在那么就创建
123 dir_create( $CONFIG [ ' templatescachedir ' ]); // 创建编译后的PHP模板目录,有关phpcms模板引擎编写。在下一章合适就开讲
124 /* *
125 dir_create() 函数为创建 目录函数。PHPCMS自己封装的,刚看了下。phpcms 挺强。这个函数还可以通过ftp 来创建目录。这样就可以解决一些 开启了安全模式下的服务器对于创建目录等出现的问题
126 因为涉及到PHP FTP 知识。所以打算讲解到下面再说。
127 */
128 }
129 cache_write( ' table.php ' , $data , ' constant ' ); // 很多朋友说找不到phpcms 表常量在那里定义的。就是在这里。
130 /* *
131 cache_write() 函数在global.func.php里面定义的。是把 已经从数据库取出来的数组信息写到 PHP文本上去。@@文本缓存关键的一步 废话少说上菜:
132 function cache_write($file, $string, $type = 'array')
133 {
134 if(is_array($string)) //检测 $string 内容是字符窜的呢还是数组的,是数组的那就继续 ..
135 {
136 $type = strtolower($type);
137 if($type == 'array')//然后再判断这个函数的模式标致 ,是否为数组模式,默认为数组模式
138 {
139 $string = "<?php"n return ".var_export($string,TRUE).";"n?>";
140 //这个太关键了。因为我们把数据库的信息写到文本上去的时候。是以符合PHP语法的格式写进去的。为什么呢?@@ 十分废话,因为如果不是以PHP格式写到文件里面去
141 那么这个PHP文件怎么能给我们include 进程序运行调用呢? 呵呵。 知道这一点就真的明白文本缓存的实现了。忒简单。 这里使用了个小技巧:使用了 var_export() 函数
142 这个函数会返回一个变量的字符窜形式。这个函数太有帮助了。如果没有这个函数,我们还要自己想办法实现呢。自己写一次文本缓存就明白了。会碰到这个问题的。 '"n' 这个是
143 文本文件的换行。初学者 别把<br> 和 '"n' 搞混罗。 一个是html 的 一个是文本文件的
144 }
145 elseif($type == 'constant') //以内容形式
146 {
147 $data='';
148 foreach($string as $key => $value) $data .= "define('".strtoupper($key)."','".addslashes($value)."');"n";
149 $string = "<?php"n".$data.""n?>";
150 如果以内容形式的话。就不是写数组到文本里面了。而是把内容都定义成常量。
151 }
152 }
153 $strlen = file_put_contents(PHPCMS_CACHEDIR.$file, $string);//file_put_contents()函数 是PHP5才支持的 效率最好。建议使用
154 chmod(PHPCMS_CACHEDIR.$file, 0777); 设置目录 为可读可写可执行
155 return $strlen; //返回写到文本的字节数
156 }
157
158 再说多一个读 缓存文件的操作函数 :上菜
159 function cache_read($file, $mode = 'i')
160 {
161 $cachefile = PHPCMS_CACHEDIR.$file;
162 if(!file_exists($cachefile)) return array();
163 return $mode == 'i' ? include $cachefile : file_get_contents($cachefile);
164 }
165 读缓存其实就是 include php缓存文件。 讲完走人
166 */
167 return $data ;
168 }
169 /* *
170 phpcms 的所有数据库表名 都用根据数据库当前的表名来用常量来进行定义。我认为这样设计不是很好。不够灵活:比如如果我们更改数据库的一个表名的话。
171 那么会出现找不到表的错误信息。而且想要修复还很麻烦。就是说不能随便更改表名了。不推荐大家这样写。我们可以把表名都定义在一个PHP文件里面。这样我们以后
172 要改某个表名,就很方便了。
173 */