帝国CMS7.5版本phome_enewssearch搜索缓存result_num数值失真问题原理与批量修复脚本
一、result_num缓存底层原理说明
帝国CMS数据表phome_enewssearch是全站搜索关键词缓存存储表,字段result_num用来记录对应关键词匹配的内容总条数,核心执行逻辑如下:
用户首次搜索某个关键词,程序会执行COUNT语句实时统计符合筛选条件的文章总量,将数字存入result_num字段保存;
后续其他用户再次搜索完全一致关键词,系统直接读取表内缓存好的result_num数值,不再重新执行统计SQL,以此降低数据库查询压力;
该缓存机制存在致命缺陷:当站点新增文章、删除文章、修改文章审核状态、修改栏目筛选条件后,phome_enewssearch内历史搜索缓存记录不会自动刷新result_num数值,缓存数字和真实文章总数不一致,造成搜索页显示文章总数失真,这也是帝国CMS搜索统计错误最普遍的成因。
phome_enewssearch内历史搜索缓存记录不会自动刷新result_num数值,我的站长站分享自己原创开发的手动批量更新result_num数值的方法。
二、批量刷新搜索结果总数PHP修复脚本
<?php
define('EmpireCMSAdmin','1');
require("../class/connect.php");
require("../class/db_sql.php");
require("../class/functions.php");
require LoadLang("pub/fun.php");
require("../class/t_functions.php");
require("../data/dbcache/class.php");
require("../data/dbcache/MemberLevel.php");
$link=db_connect();
$empire=new mysqlquery();
$sid = isset($_GET['startid']) ? (int)$_GET['startid'] : 0;
$batchLimit = 20;
$maxSearchid = 0;
$sql = $empire->query("SELECT searchid,tbname,andsql FROM {$dbtbpre}enewssearch WHERE searchid > {$sid} ORDER BY searchid ASC LIMIT {$batchLimit}");
$hasData = false;
while($r = $empire->fetch($sql))
{
$hasData = true;
$maxSearchid = $r['searchid'];
$tb = $r['tbname'];
$whereSql = stripslashes($r['andsql']);
$searchId = $r['searchid'];
if(empty($tb))
{
$empire->query("UPDATE {$dbtbpre}enewssearch SET result_num=0 WHERE searchid={$searchId}");
continue;
}
// 处理andsql三种格式:空条件、where开头、and/or开头
$whereSqlTrim = trim($whereSql);
if($whereSqlTrim === '')
{
$fullWhere = '';
}
elseif(strtolower(substr($whereSqlTrim,0,4)) == 'where')
{
$fullWhere = ' '.$whereSqlTrim;
}
else
{
// 以and/or开头,拼接WHERE 1=1规避SQL语法报错
$fullWhere = ' WHERE 1=1 '.$whereSqlTrim;
}
$countSql = "SELECT COUNT(*) AS total FROM {$dbtbpre}ecms_{$tb}{$fullWhere}";
$countRow = $empire->fetch1($countSql);
$total = (int)$countRow['total'];
// 更新当前搜索缓存的真实文章总数
$empire->query("UPDATE {$dbtbpre}enewssearch SET result_num={$total} WHERE searchid={$searchId}");
}
if(!$hasData)
{
echo "全部搜索记录重新统计完成!";
db_close();
$empire = null;
exit;
}
// 1秒自动跳转批量处理下一批搜索缓存
echo '<meta http-equiv="refresh" content="1;url=ChangeByID.php?startid='.$maxSearchid.'">';
echo "本批处理完毕,当前最大searchid:".$maxSearchid.",自动处理下一批...";
db_close();
$empire = null;
?>三、脚本运行逻辑拆解
1、分批读取搜索缓存数据
通过GET传参startid记录处理进度,单次批量读取20条enewssearch搜索缓存记录,避免一次性查询全表导致数据库负载过高,循环自动分页处理所有缓存。
2、兼容三种筛选条件SQL格式
空筛选条件:直接不拼接WHERE语句,统计栏目全部内容;
原生以where开头的筛选语句:直接拼接使用;
以and、or开头的碎片条件:补充WHERE 1=1作为前置条件,防止SQL语法执行报错;
3、实时统计真实数据并更新缓存
根据每条搜索记录绑定的数据表名、筛选SQL,执行COUNT查询获取当前真实文章数量,同步更新对应searchid的result_num字段,彻底修复数值失真问题;数据表为空的无效缓存直接置result_num为0。
4、自动循环分批执行
单批20条处理完成后,页面1秒自动刷新跳转,携带当前最大searchid继续读取下一批数据;当查询不到新缓存记录时,输出完成提示并终止程序。
四、脚本部署与使用步骤
将代码保存为ChangeByID.php,上传至帝国CMS后台admin目录;
登录网站后台管理员账号,浏览器访问 /admin/ChangeByID.php;
页面自动分批刷新执行,等待出现“全部搜索记录重新统计完成”即修复结束;
执行完成后可删除该脚本文件,避免他人访问造成数据库重复查询;
五、补充注意事项
1、脚本需要管理员后台权限,必须登录后台后访问才能正常执行,直接外网访问会拦截;
2、站点搜索缓存数据量大时,完整刷新耗时会变长,请勿中途关闭页面;
3、仅修复历史缓存的result_num数值,不会改动站点原有搜索缓存机制,无副作用;
4、后续频繁增删文章的站点,可定期运行该脚本,保证搜索页面展示总数准确。
六、总结
这套批量修复脚本针对性解决帝国CMS搜索缓存result_num不会自动更新的核心BUG,分批处理降低数据库压力,兼容系统所有搜索筛选SQL格式,一键自动刷新全站所有关键词的真实文章统计数量,彻底解决搜索列表页面文章总数显示错误的问题,适配帝国CMS7.5、8.0全版本使用。
