typecho 是一个伪静态的博客系统,如果不使用缓存,每次打开页面都会查询数据库,访问人数多了以后服务器压力倍增。
但是,typecho 是一个 php 的程序,我们可以利用 php 将实时页面保存成 html,设置一个失效时间,如果在失效时间内就不用查询数据库重新生成页面,直接返回 html 即可。
1、设置缓存文件保存目录
在 typecho 根目录下,新建一个 cache 目录,授予可写权限
2、PHP 配置
PHP.ini 环境配置文件要改一下,将 allow_url_include = On
3、设置缓存
1)打开根目录下的 index.php 文件,在 /** 初始化组件 */
上方添加如下代码:
$file = $_SERVER['REQUEST_URI']; // 获取访问url
$htmlfile='./cache/'.md5($file).'.html'; // url使用md5加密后生成缓存文件路径
// echo($htmlfile);
// 如果是 get 请求,并且对应缓存文件存在,并且文件创建时间小于 600 秒,就直接返回配置文件
if($_SERVER['REQUEST_METHOD']=='GET' and file_exists($htmlfile) and ((time()-filemtime($htmlfile))< 600)){
include($htmlfile);
exit;
}
2)在 index.php 文件的最后,添加如下代码:
// 如果请求是get,并且不是评论相关的页面,则进行缓存
if($_SERVER['REQUEST_METHOD']=='GET' and strpos($file,'comment')<1 and strpos($file,'feed')<1 and strpos($file,'sitemap')<1){
$content=ob_get_contents(); //得到缓冲区的内容
file_put_contents($htmlfile, $content); //写入缓存文件
}
添加完之后如图:
1、上边代码添加完之后,访问一次首页,看看 cache 目录是否生成了相关缓存文件; 2、可以用 php 语言在网站页面底部添加一个时间,生成缓存之后刷新页面,看时间变不变; 3、感受一下页面打开速度;
附:本站页面底部时间生成代码:
<?php echo date("Y-m-d H:i:s");?>
由于本站浏览量是在 functions.php 文件里添加如下代码实现的:
function Postviews($archive) {
$db = Typecho_Db::get();
$cid = $archive->cid;
if (!array_key_exists('views', $db->fetchRow($db->select()->from('table.contents')))) {
$db->query('ALTER TABLE `'.$db->getPrefix().'contents` ADD `views` INT(10) DEFAULT 0;');
}
$exist = $db->fetchRow($db->select('views')->from('table.contents')->where('cid = ?', $cid))['views'];
if ($archive->is('single')) {
$cookie = Typecho_Cookie::get('contents_views');
$cookie = $cookie ? explode(',', $cookie) : array();
if (!in_array($cid, $cookie)) {
$db->query($db->update('table.contents')
->rows(array('views' => (int)$exist+1))
->where('cid = ?', $cid));
$exist = (int)$exist+1;
array_push($cookie, $cid);
$cookie = implode(',', $cookie);
Typecho_Cookie::set('contents_views', $cookie);
}
}
echo $exist;
}
这就导致设置缓存以后,浏览量不会增加了,如果是跟我一样的浏览量实现方式,可以在 functions.php 文件里增加如下函数:
function addPostviews($cid) {
$db = Typecho_Db::get();
if (!array_key_exists('views', $db->fetchRow($db->select()->from('table.contents')))) {
$db->query('ALTER TABLE `'.$db->getPrefix().'contents` ADD `views` INT(10) DEFAULT 0;');
}
$exist = $db->fetchRow($db->select('views')->from('table.contents')->where('cid = ?', $cid))['views'];
$cookie = Typecho_Cookie::get('contents_views');
$cookie = $cookie ? explode(',', $cookie) : array();
if (!in_array($cid, $cookie)) {
$db->query($db->update('table.contents')
->rows(array('views' => (int)$exist+1))
->where('cid = ?', $cid));
$exist = (int)$exist+1;
array_push($cookie, $cid);
$cookie = implode(',', $cookie);
Typecho_Cookie::set('contents_views', $cookie);
}
echo $exist;
}
然后在 post.php 文件顶部增加如下代码:
<?php
// 判断是否是浏览量的 POST 请求
if (isset($_POST['view'])) {
// 判断 POST 请求中的 cid 是否是本篇文章的 cid
if ($_POST['view'] == $this->cid) {
// 调用点赞函数,传入文章的 cid
exit(addPostviews($this->cid));
}
// 如果点赞的文章 cid 不是本篇文章的 cid 就输出 error 不再往下执行
exit('error');
}
?>
最后用 js 在 post.php 文件底部增加一个 post 请求就行了:
// 浏览量
$.post('<?php $this->permalink(); ?>',{'view':<?php echo $this->cid; ?>},function(result){
console.log(result);
});
导致这个问题的原因是,原来的浏览量增加是利用 php 函数获取浏览量的同时增加浏览量,但是缓存之后的 html 页面已经没有 php 的代码了,只有 php 缓存的时候生成的结果,所以相应的浏览量肯定不会增加了,但是 js 代码是会缓存到 html 中的,所以我们利用 js 发送一个 post 请求,后端接收到请求去更新一下浏览量就可以解决了。