当前位置: 首页 > news >正文

PHP插件开发中的一个错误:JSON直接输出导致网站首页异常

问题描述

最近在使用步数统计插件(WeFootStep)时,发现网站首页完全变成了一段JSON数据,而不是正常的HTML页面。具体表现为首页显示如下内容:

{"results":"<li><a href=\"https:\/\/blog.ybyq.wang\/archives\/186.html\">\u770b\u770b\u4f60\u662f\u4e0d\u662f\u201c\u8d5e\u535a\u6587\u76f2\u201d<p class=\"text-muted\">dobe\u3001IDEA\u3001<mark class='text_match'>pycharm<\/mark>\u7b49\r\n<\/p><\/a><\/li>..."}


这完全破坏了网站的正常浏览体验。

原因分析

经过几天的艰苦排查,发现问题出在WeFootStep插件的Widget.php文件中的getStepDataJson()函数:

/*** 获取步数JSON数据,用于AJAX请求*/
public function getStepDataJson()
{$history = $this->getStepHistory();$stats = $this->getStepStats();$data = ['history' => $history,'stats' => $stats];header('Content-Type: application/json');echo json_encode($data);exit;
}

这个函数存在的问题是:

  1. 函数直接设置了响应头为application/json
  2. 输出JSON编码后的数据
  3. 调用exit终止了PHP的执行流程

这种实现方式本来是为AJAX请求设计的,但如果在普通页面加载过程中被误调用,就会导致整个页面只输出JSON数据。

解决方案

解决方案很简单:修改getStepDataJson()函数,让它只在确认是AJAX请求时才直接输出JSON并退出:

/*** 获取步数JSON数据,用于AJAX请求*/
public function getStepDataJson()
{$history = $this->getStepHistory();$stats = $this->getStepStats();$data = ['history' => $history,'stats' => $stats];// 只在AJAX请求时才直接输出JSON并退出if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {header('Content-Type: application/json');echo json_encode($data);exit;}// 如果不是AJAX请求,返回数据而不直接输出return $data;
}

这个改进添加了一个检查机制,通过判断$_SERVER['HTTP_X_REQUESTED_WITH']是否为xmlhttprequest来确定当前是否是一个AJAX请求。如果是,才执行原来的行为;如果不是,则只返回数据而不直接输出。

技术要点

  1. AJAX请求的识别:通常AJAX请求会包含X-Requested-With: XMLHttpRequest头,这是检测AJAX请求的标准方法。

  2. 避免直接输出:在MVC架构的应用中,控制器方法通常不应该直接输出内容,而是返回数据让框架处理。

  3. 避免无条件退出exitdie会立即终止PHP的执行,应谨慎使用,尤其是在可能被其他代码调用的函数中。

教训与最佳实践

在开发PHP插件或组件时,应遵循以下原则:

  1. 关注点分离:数据处理与输出应该分开,不要在获取数据的函数中直接输出。

  2. 条件性输出:如果必须在函数中输出,应该有明确的条件控制。

  3. 防御性编程:总是假设你的函数可能在意外的情况下被调用,添加适当的检查。

  4. 明确文档:清晰记录函数的行为和副作用,特别是那些会改变HTTP头或直接输出的函数。

这个简单的修改解决了首页显示JSON数据的问题,也提醒我们在插件开发中要注意代码的健壮性和兼容性。


作者:xuan
个人博客:https://blog.ybyq.wang
原文链接:https://blog.ybyq.wang/archives/770.html
欢迎访问我的博客,获取更多技术文章和教程。

http://www.dtcms.com/a/298487.html

相关文章:

  • 零碳园区如何破局?安科瑞EMS3.0以智慧能源管理重构低碳未来
  • 焊接机器人节能先锋
  • Seaborn可视化
  • MYOJ_8516:CSP初赛题单8:计算机语言和信息编码
  • 工作学习笔记(深圳xxx公司软件工程师助理)
  • Map学习笔记
  • 扫描对方是否开启局域网远程桌面
  • Windows安装压缩包形式的PostgreSQL
  • Python 列表排序:快速上手指南
  • Palindrome Reorder
  • 腾讯研究院:AI Coding引发编程范式革命
  • 微信小程序动态切换窗口主题色
  • 多智能体强化学习入门:从基础到 IPPO 算法—强化学习(20)
  • 2507C++,C++协程的发送者
  • 浅谈生成式AI语言模型的现状与展望
  • haproxy七层代理(原理)
  • SawtoothSoftware 模板注入漏洞复现(CVE-2025-34300)
  • 8.异常处理:优雅地处理错误
  • ISIS高级特性GR
  • Springboot+activiti启动时报错XMLException: Error reading XML
  • 优思学院|QC七大手法之一的检查表应如何有效使用?
  • 【unitrix】 6.15 “非零非负一“的整数类型(NonZeroNonMinusOne)特质(non_zero_non_minus_one.rs)
  • 亚马逊广告策略:如何平衡大词和长尾词的效果?
  • 倩女幽魂手游代言人杨洋携剑仙入世 仙姿临世锋芒毕露
  • docker-compose:未找到命令的检查步骤和修复
  • ABP VNext + OData:实现可查询的 REST API
  • 服务端处于 TIME_WAIT 状态的 TCP 连接,收到相同四元组的 SYN 后会发生什么?详解
  • HCIP上HCIA复习静态综合实验
  • 移动端设备能部署的llm
  • 系统日志与用户信息绑定实现日志跟踪