为什么调用一次file_put_contents会向JSON文件插入2行数据?
问题原因
你插入的两条数据id和name均为不同的随机值,说明整个插入逻辑被触发了两次,并非create方法内部逻辑有问题,大概率是以下两种场景导致:
- Web访问场景下的重复请求:最常见的是浏览器自动请求
favicon.ico,如果你的服务端没有配置静态资源独立处理,所有请求都会转发到PHP入口脚本,相当于代码被执行了两次。也有可能是服务器配置了请求超时自动重试,或者路由规则异常导致单次请求调度了两次插入逻辑。 - 命令行执行场景下的重复触发:比如脚本执行时不小心运行了两次,或者框架的指令调度逻辑重复调用了插入代码。
排查&修复方案
- 先确认
create方法的调用次数,在create方法第一行加入调试日志:
执行一次插入逻辑后查看public function create(array $newData): int { // 加入调试日志,确认调用次数 file_put_contents(__DIR__.'/debug.log', date('Y-m-d H:i:s')." 调用create,数据:".json_encode($newData).PHP_EOL, FILE_APPEND); $fileData = $this->readTable(); $fileData[] = $newData; $this->writeTable($fileData); return $newData[$this->primaryKey]; }debug.log的行数,如果有两条日志,即可确认是逻辑被重复触发。 - 如果是Web访问场景,在入口文件最开头加入favicon请求拦截:
if (isset($_SERVER['REQUEST_URI']) && $_SERVER['REQUEST_URI'] === '/favicon.ico') { http_response_code(404); exit; } - 优化JSON文件读写逻辑,加独占锁避免并发请求导致的数据覆盖问题,修改
writeTable方法:private function writeTable($fileData){ $fileDataJson = json_encode($fileData); $fp = fopen($this->tableFilePath, 'w'); if (flock($fp, LOCK_EX)) { // 加写独占锁,阻塞其他进程访问 fwrite($fp, $fileDataJson); flock($fp, LOCK_UN); // 释放锁 } fclose($fp); }
内容的提问来源于stack exchange,提问作者Pouya Parsaei
相关产品推荐
相关产品推荐

