当前位置:首页 > AI技术 > 正文内容

Think怎么实现阅读计数 Think文章浏览量统计技巧操作实战案例|Duuu笔记

admin2个月前 (03-31)AI技术52

阅读数未更新主因是缓存干扰或条件不匹配:ThinkPHP默认开启查询缓存,若误用cache(true)或全站缓存中间件,读取仍返回旧值;需检查ID类型是否一致、SQL条件是否命中,并确保setInc在控制器中执行而非模板内。

为什么

update

之后阅读数没变?

常见现象是:文章页每次刷新都调用

Db::name('article')->where('id', $id)->setInc('view_count')

,但数据库里数字不动。原因多半是缓存没关或条件没命中——ThinkPHP 默认开启查询缓存,

setInc

属于写操作,但若上层用了

cache(true)

或开启了全站缓存中间件,读取时可能仍返回旧值。

确认是否在控制器/模型中误加了

->cache(true)

链式调用

检查数据库连接配置里的

'resultset_type' => 'collection'

是否影响了写后立即读(一般不影响,但搭配某些缓存驱动会出问题)

Db::getLastSql()

打印实际执行的 SQL,看 WHERE 条件是否真能匹配到记录(比如

$id

是字符串而数据库字段是 int,隐式转换失败)

并发下

setInc

会不会丢计数?

会,但概率低。ThinkPHP 的

setInc

底层是

UPDATE ... SET view_count = view_count + 1

,MySQL 在行级锁支持下基本能保证原子性。但如果业务量大(比如秒杀级文章爆火),仍可能出现多个请求同时读到同一旧值、再各自+1写回的情况——这不是 ThinkPHP 的锅,是 SQL 层面未加锁导致。

高并发场景建议改用原生 SQL 加

FOR UPDATE

(需事务包裹):

Db::startTrans();
Db::query('SELECT view_count FROM think_article WHERE id = ? FOR UPDATE', [$id]);
Db::name('article')->where('id', $id)->setInc('view_count');
Db::commit();

更轻量的解法是用 Redis 计数器:先

INCR article:views:$id

,再定时同步回 MySQL,避免 DB 成为瓶颈

注意:Redis 方案要处理“页面首次加载即触发计数”的时机——不能等 JS 异步上报,得服务端直出时就 incr

怎么区分真实用户和爬虫?

直接对所有

GET /article/123

请求加

setInc

,会导致搜索引擎、健康检查、监控探针把阅读数刷爆。必须过滤。

独响

一个轻笔记+角色扮演的app

下载

基础判断:检查

$_SERVER['HTTP_USER_AGENT']

是否含

bot

spider

crawler

(不区分大小写),但容易误伤 RSS 阅读器

更稳的做法是结合

$_SERVER['HTTP_X_FORWARDED_FOR']

和 IP 频率限制——比如同一 IP 5 分钟内只记 1 次

推荐组合策略:

if (!is_bot() && !is_repeated_view($ip, $article_id)) {
Db::name('article')->where('id', $id)->setInc('view_count');
}

其中

is_repeated_view

可用 Redis 的

SETNX article:seen:$ip:$id

+ 过期时间实现

setInc

和手动

update

哪个更安全?

setInc

更安全。手动写

update(['view_count' => $old + 1])

要先

select

update

,中间有竞态窗口;而

setInc

是单条 SQL,MySQL 自己保证原子性。

PHP免费学习笔记(深入)

”;

但注意:如果字段允许 NULL,

setInc

对 NULL 值会变成

NULL + 1 → NULL

,结果仍是 NULL。务必初始化为 0:

Db::name('article')->where('id', $id)->update(['view_count' => 0]);

如果需要带条件更新(比如仅登录用户才计数),

setInc

不支持 where 外的额外条件,得换

update

+ 事务兜底

性能上无差别,底层都是 UPDATE;但

setInc

少一次 PHP 层变量计算,代码更干净

真实项目里最常被忽略的,是「计数时机」——很多人在模板里用

{:Db::name('article')->where('id', $id)->value('view_count')}

直接查,却忘了这行代码本身不会触发

setInc

。阅读数增加和展示必须拆成两个明确动作,且增加操作得放在控制器逻辑里,不能依赖模板渲染时顺手做。

相关文章

一文讲清神经网络、BP神经网络、深度学习的关系

人工神经网络中的顶级代表。往往说《神经网络》就是指《BP神经网络》。 大家研究着各种神经网络,研究得不亦乐乎, 来了两个家伙Romelhart 和Mcclelland,...

前端开发实战详解:骡子快跑怎么注册账号 骡子快跑账号注册流程最佳实践|Duuu笔记

骡子快跑注册仅需1分钟,但激活码需从Discord指定频道获取,输错3次将锁账户24小时;积分与注册邮箱强绑定且不可更换;部分地区即使注册成功也无法运行Agent。 ☞☞☞AI 智能聊天, 问答助手...

深入理解前端开发:Minimax 视频生成中负面提示词(Negative Prompt)写法完全指南|Duuu笔记

Minimax视频生成中负面提示词需用英文、逗号分隔,支持权重调节(如(blurry:1.3)),按构图/主体/画质/风格四类精简选取,禁用not/no/中文及违规词,须通过A/B测试验证有效性。...

前端开发高级应用:Minimax视频生成提示词中文还是英文好实战案例|Duuu笔记

优先使用英文提示词,因其更契合模型训练语料并能稳定触发视觉特征;其次可采用中英混合策略兼顾文化专有名词;纯中文适用于强本土化场景;最终需通过多指标对比验证最优语言形式。 ☞☞☞AI 智能聊天, 问答...

深入理解前端开发:零基础教程:怎么用 Gemini 自动生成短视频脚本与拍摄大纲完全指南|Duuu笔记

需明确输入指令、理解输出逻辑并合理拆解内容:一、构建含角色/任务/格式等要素的提示词;二、追加分镜与时间轴约束优化专业性;三、转译为带道具编号与颜色标记的执行清单;四、用Gemini校验注意力断点并迭...

前端开发高级应用:骡子快跑支持日程安排吗 骡子快跑时间管理助手用法实战案例|Duuu笔记

骡子快跑具备日程安排能力,可通过计算机模式构建长效日程代理、自然语言注入日历事件、绑定外部日历实现双向同步三种方式实现。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 Dee...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。