当前位置: 首页 > 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.lryc.cn/news/600103.html

相关文章:

  • 纸板留声机:用ESP32和NFC打造会唱歌的复古装置
  • 手语式映射:Kinova Gen3 力控机械臂自适应控制的研究与应用
  • 秒收蜘蛛池解析机制的原理
  • PPIO上线阿里旗舰推理模型Qwen3-235B-A22B-Thinking-2507
  • ATR2652SGNSS全频段低噪声放大器
  • PostgreSQL对象权限管理
  • GPU 驱动安装升级测试
  • [NPUCTF2020]ReadlezPHP
  • CSS 盒子模型学习版的理解
  • C语言第 9 天学习笔记:数组(二维数组与字符数组)
  • ODFM(正交频分复用)系统中加入汉明码(Hamming Code)的主要目的是增强抗误码能力,通过**前向纠错(FEC)**机制提高传输可靠性
  • KNN算法:从原理到实战全解析
  • Kubernetes深度解析:企业级容器编排平台的核心实践
  • 内存 管理
  • LeetCode 233:数字 1 的个数
  • ACL:访问控制列表
  • 大数据中心——解读60页IDC云数据中心机房运维服务解决方案【附全文阅读】
  • MMRotate ReDet ReFPN 报错 `assert input.type == self.in_type`
  • Linux的磁盘存储管理实操——(下二)——逻辑卷管理LVM的扩容、缩容
  • ComfyUI中运行Wan 2.1工作流,电影级视频,兼容Mac, Windows
  • 一些常见的网络攻击方式
  • 与 TRON (波场) 区块链进行交互的命令行工具 (CLI): tstroncli
  • 关闭chrome自带的跨域限制,简化本地开发
  • 【Chrome】下载chromedriver的地址
  • 中国航天集团实习第一周总结
  • 低速信号设计之 SWD 篇
  • 随机抽签服务API集成指南
  • python学习DAY22打卡
  • 如何评估一个RWA项目的可信度?关键指标解析
  • 图书推荐-由浅入深的大模型构建《从零构建大模型》