WordPress缓存导致文章阅读数点赞数不更新这个问题应该很多WordPress站长遇到过,因为WordPress提速最简单的就是缓存,这种方案也收到广大个人站长的一致追捧,然而一缓存网页就成静态了,不会有PHP交互也就不会更新数据,难道缓存和阅读计数不能同时拥有吗?当然有而且还不止一种,天无绝人之路嘛,下面就是一种解决整个页面被缓存而导致文章阅读数点赞数不更新的解决办法。
先声明下,由于原理一样,我这里就用阅读数做例子,点赞数就不讲了。并且这个办法不适用于内存缓存,因为内存缓存失效时还是会执行PHP代码计数的,使用这个方法的话会导致阅读数不够准确。如果是内存缓存用户,建议使用这里的方案,将阅读数存到内存中,等数量到了指定界限时,一次性写入阅读数,不过这样会出现阅读数无法及时更新的尴尬情况。
解决办法一:
首先,我们在网站的根目录新建一个操作文件,命名为views.php
,将以下代码写入此文件中。
<?php
require('../../wp-blog-header.php');
$isXhr = $_SERVER['HTTP_X_REQUESTED_WITH'];
if (strtoupper($isXhr) == strtoupper("XMLHttpRequest")) {
$post_id = $_POST['post_id'];
$po = get_post_meta($post_id,'views',true);
if(!$po) {
//表示不存在这个自定义栏目,那么新增这个自定义栏目
add_post_meta($post_id, 'views', 1, true);
echo 1;
} else {
// 若已存在这个自定义栏目,则先获取当前数值,并递增+1,再更新数据库
$count = $po + 1;
update_post_meta($post_id,'views',$count);
echo $count;
}
} else {
header("Status: 403 Not Found");
exit;
}
接着我们在主题的page.php文件中插入以下代码:
$(function(){
function page_views() {
if(!window.localStorage) {
console.info('浏览器不支持localStorage');
}else{
var post_id = <?php the_ID();?>;
var views = localStorage.getItem("view_list");
if(views===null){
localStorage.setItem("view_list",post_id);
$.post("/views.php?time="+new Date().getTime(),{post_id:post_id});
return true;
}else{
var item = views.split("|");
var bool = $.inArray(post_id+'',item);
if(bool===-1){
$.post("/views.php?time="+new Date().getTime(),{post_id:post_id});
localStorage.setItem("view_list",views+"|"+post_id);
return true;
}
return false;
}
}
}
page_views();
});
到这一步,就已经成功解决了这个问题。
具体效果见本站,这种方法适用于被腾讯CDN或者其它CDN缓存了整个页面的情况,也适用于被WordPress插件wp_super_cache缓存了整个页面的情况,这里就不一一举例了,试试看就知道效果。唯一的缺点就是有些浏览器如果禁止执行js,那么我们的阅读数就失效了,还有就是js执行post操作需要时间,如果用户打开一瞬间就关闭网页,那么阅读数量也是无法更新的。
解决办法二:
使用ajax获取文章阅读数量并刷新网页中阅读数量的HTML标签,服务器收到请求后,同时将原来的阅读数量加1并更新到数据库中。说到这里最关键的内容就是ajax提交请求了,既然是请求那就需要接口了,不然不知道请求谁呀,下面是一个简单的请求接口,大家参考下。
PHP接口文件
将下面的代码复制保存为views.php文件,并放在主题目录下的action目录中,没有就新建一个action文件夹。
require( dirname(__FILE__).'/../../../../wp-load.php' );
nocache_headers();
$post_ID = isset($_POST['post_ID']) ? (int) $_POST['post_ID'] : 0;
if ($post_ID!=0 ) {
$post_views = (int) get_post_meta($post_ID, 'views', true);
if (!update_post_meta($post_ID, 'views', ($post_views + 1))) {
add_post_meta($post_ID, 'views', 1, true);
}
$post_views = (int) get_post_meta($post_ID, 'views', true);
print_r(json_encode(array('error' => 0, 'views' => 1, 'response' => $post_views)));
exit;
}else{
print_r(json_encode(array('error' => 1, 'views' => 0, 'response' => $post_views)));
exit;
}
上面第一行代码是引入WordPress函数核心支持,没有这个文件我们就不能使用WordPress提供的函数。接着输出响应头部无缓存,然后判断post参数post_id这个是用来区分是哪篇文章的,没接收到就赋值0,后面就是一些逻辑操作和存储自定义字段内容的函数,就不多做解释了,最后以json数据的形式输出提交的详情和阅读数量。
注意:add_post_meta函数存储的自定义字段根据你自己的阅读数量字段修改,我使用的是大前端dux的文章阅读数量字段。
jQuery请求数据
把上面的文件存储到服务器中,我们就可以使用下面的代码来执行js操作请求数据,在这之前先说一下,jQuery必须在下面js之前引用,并且下面js在加载前HTML必须先加载,否则无效。
//获取阅读数
function getpostviews(postid){
$.ajax({
type: "POST",
url: 'https://www.xxx.com/wp-content/themes/dux/action/views.php',
dataType: "json",
data: {"post_ID": postid},
success: function(data, textStatus, xhr) {
if (data.error){ return false;}else{
$(".postviews").text("阅读("+data.response+")");
}
}
});
}
上面的postviews是我的文章阅读数量HTML标签的class名称,根据自己的主题修改,然后在主题的文章页模板single.php中写输出js代码:
<?php
<script type="text/javascript">
$(document).ready(function (){
echo 'getpostviews('.get_the_ID().');';
});
</script> ?>
当然,除了文章页,页脚也可以输出,不过为了避免在页面中加载这个函数,所以我们可以使用is_single函数判断下是不是文章页,代码简单这里就不说了。具体效果见本站,这种方法适用于被腾讯CDN或者其它CDN缓存了整个页面的情况,也适用于被WordPress插件wp_super_cache缓存了整个页面的情况,这里就不一一举例了,试试看就知道效果。唯一的缺点就是有些浏览器如果禁止执行js,那么我们的阅读数就失效了,还有就是js执行post操作需要时间,如果用户打开一瞬间就关闭网页,那么阅读数量也是无法更新的。