自定义PHP日志功能出现重复日志条目问题排查求助
问题成因
日志重复写入的核心原因是**controller.php被执行了两次**,触发源是.htaccess配置结合浏览器的默认行为:
- 访问站点根目录时,服务器通过
DirectoryIndex controller.php加载controller.php,执行日志写入逻辑; - 浏览器会自动请求站点的
favicon.ico(网站图标),该文件不存在时,你的Rewrite规则会将这个请求转发到controller.php,导致脚本被第二次执行。由于两次请求间隔极短,时间戳完全一致,最终生成重复日志。
你可以在controller.php开头添加var_dump($_SERVER['REQUEST_URI']);验证,会看到两次请求的URI分别是/和/favicon.ico。
修复方法
推荐以下几种解决方案,按优先级排序:
方案1:添加真实的favicon.ico文件
直接在站点根目录放置一个favicon.ico文件,浏览器会请求这个真实存在的资源,不会触发Rewrite规则转发到controller.php。
方案2:修改.htaccess,排除静态资源的Rewrite
在原有Rewrite规则前添加一条规则,跳过对favicon.ico的转发处理:
# 跳过favicon.ico的Rewrite规则 RewriteRule ^favicon.ico$ - [L] # 原有的Rewrite规则 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^([^/]+)/?$ controller.php?page=$1 [QSA,NC,L]
-[L]表示不对该请求应用后续Rewrite规则,直接返回原资源(不存在则返回404),不会转发到controller.php。
方案3:在controller.php中过滤非页面请求
在controller.php的最开头添加判断,直接退出静态资源请求的处理:
// 过滤favicon.ico等非业务请求 if ($_SERVER['REQUEST_URI'] === '/favicon.ico') { exit; }
这样即使请求被转发到controller.php,也会直接终止执行,不会触发日志写入逻辑。
额外优化建议
- 你的
Report::notice方法返回类型是void,但controller.php中用了if(Report::notice(...))判断,这在PHP中会因为void返回null导致条件永远为false,可以修改notice方法返回write的结果:
public static function notice(string $message): bool { return Report::write('notice', $message, 'notice'); }
- 日志写入时建议增加文件锁,避免并发场景下的日志错乱:
// 替换原有的file_put_contents逻辑 $handle = fopen($file, 'a'); if ($handle) { flock($handle, LOCK_EX); // 独占锁 fwrite($handle, $message . PHP_EOL); flock($handle, LOCK_UN); // 释放锁 fclose($handle); } else { return false; }
内容的提问来源于stack exchange,提问作者Ere Männistö
相关产品推荐
相关产品推荐

