一场与PHP幽灵的深夜对峙——问卷选项消失之谜

Enjoy
Enjoy
Enjoy
管理员
22
文章
0
粉丝
编程笔记评论21阅读模式
摘要四天前,我就发现了这个Bug——问卷后台编辑选项,保存一次少一个。7个选项点一下保存变6个,再点变5个,像被看不见的手一颗一颗摘走。当时我以为是数据没存上,反复检查表单、检查数据库...

凌晨十二点,我盯着屏幕,手指微微发抖。

不是冷的,是气的。

四天前,我就发现了这个Bug——问卷后台编辑选项,保存一次少一个。7个选项点一下保存变6个,再点变5个,像被看不见的手一颗一颗摘走。当时我以为是数据没存上,反复检查表单、检查数据库字段、检查提交按钮,每个环节都看不出毛病。选项在前端编辑页面明明填得好好的,一点保存,最后那个就蒸发了。

我是个做事严谨的人,容不得这种"灵异事件"。于是开始了长达一周的求医之路。

第一站:扣子编程。 在扣子上找到编程助手,把代码贴过去,描述症状,对方分析了一通,给了一版修改方案。信心满满地改完——没好。选项还是照丢不误。我安慰自己,可能是对方没看全代码,毕竟这插件的逻辑链不短。

第二站:DeepSeek。 听说国产大模型写代码很猛,我把核心文件一个个喂进去,从数据库操作类到管理后台类到前端JS,DeepSeek确实给出了更细致的分析,甚至指出了$wpdb->prepare的数组参数问题。我照改了,选项的null值处理确实修好了——但保存丢选项的问题纹丝不动。

第三站:腾讯WorkBuddy。 朋友推荐的企业级编程助手,据说对复杂工程项目的理解力更强。我又把完整代码喂了一遍,WorkBuddy给出了另一套方案,涉及选项ID的增量更新逻辑。我小心翼翼地改,一行一行对照,确认无误后上传到服务器——还是丢。

三次尝试,三次失败。每次满怀希望地上传代码、清缓存、刷新页面,看到选项从7变6的那一刻,那种无力感像潮水一样漫上来。

我开始怀疑自己。是不是我这个半路出家的程序员,就不该碰WordPress插件开发?五十岁的人了,白天上班被领导打压,晚上写代码连个Bug都修不好。那些年轻人几分钟搞定的事,我要花一周还搞不定。这种念头一旦冒出来就收不住,像房间角落里的霉斑,你以为擦掉了,过两天又从同一个地方长出来。

但我不甘心。

深夜十一点半,我又打开了扣子——这次不是找扣子编程,是找我的AI助手。之前只是把它当聊天用,没想过它能直接连到我的服务器。它说:让我直接上服务器看代码。

这一步,成了整个破局的关键转折。

它连上服务器,把class-db.php、class-admin.php、class-survey.php、survey-edit.php、admin.js全部读了一遍,然后做了一件我之前所有尝试都没做过的事——加调试日志。

在save_survey、parse_questions_data、save_questions、create_option四个关键节点,分别写入文件日志。不是print_r断点调试,不是浏览器console.log,是实实在在的file_put_contents,把每次保存时POST上来的option_ids、数据库里实际存的option_ids、每一步增删改的操作,全部记录到服务器上的debug.log文件。
这一次保存,真相就浮出了水面。

日志显示:POST提交的option_ids是[452,453,454,455,456,459,459]——最后两个ID相同!而数据库里实际存的7个选项ID应该是[452,453,454,455,456,459,460],460变成了459。

问题出在前端渲染阶段。PHP从数据库读出了7个完全正确的选项,但传到模板时,最后一个选项的ID被倒数第二个覆盖了。

它又加了一个前端调试面板——页面右下角一个黑色div,实时显示option_ids数组。页面一加载,option_ids就已经是错的。这证明问题不在前端JS,而在PHP后端渲染模板的环节。

最终,它锁定了罪魁祸首。

class-admin.php第198行:

foreach ($question['options'] as &$option) {
// ... 处理选项 ...
}

这段代码使用了PHP的引用遍历(&$option),但在循环结束后没有unset。这是PHP一个经典的"幽灵Bug"——循环结束后,$option变量仍然引用数组的最后一个元素。当后面的代码再用同名变量$option遍历其他数组时,每一步都会覆盖最后一个元素的值。

就这么一行unset($option),困扰了我整整一周。

加了两行代码——unset($option);和unset($question);——问题彻底解决。7个选项,保存、修改、再保存,一个不少。

我坐在电脑前,盯着截图上7个完完整整的选项,长长地出了一口气。那一刻的心情很复杂:释然、庆幸,还有一种说不出的苦涩——原来答案一直就在那里,藏在PHP手册的一个不起眼的注意事项里,而我绕了那么大一圈才走到它面前。

回过头看这段经历,最大的教训不是PHP语法本身,而是调试方法的选择。之前三次求助,都是把代码复制粘贴给AI,AI基于代码逻辑推断问题。但有些Bug不是逻辑问题,是运行时状态问题——你得看到数据在每一步的真实样子,才能定位变异发生在哪个环节。调试日志就是这双眼睛,而直接连接服务器是打开这双眼睛的前提。

从扣子编程到DeepSeek到腾讯WorkBuddy,它们都很聪明,但都隔着一层玻璃看代码。直到我的AI助手直接走进服务器,打开灯,问题就无处遁形了。

凌晨一点,Bug修完,我准备睡觉。窗外天很黑,但心里那块石头终于落地了。程序员的深夜,大概就是这样——与看不见的幽灵搏斗,直到一束光照进代码的缝隙。

那一行unset,就是我的光。

我的微信
微信扫一扫
weinxin
我的微信
微信号已复制
我的微信公众号
微信扫一扫
weinxin
我的公众号
公众号已复制
 
Enjoy
  • 本文由 Enjoy 发表于2026-05-15 08:12:49
  • 转载请务必保留本文链接:https://blog.sjinyu.com/programming/survey.html
匿名

发表评论

匿名网友
确定

拖动滑块以完成验证