PHP接口返回JSON需严格匹配前端图表库格式要求,正确处理数据类型、日期格式、聚合逻辑、错误响应及安全过滤,避免前端图表空白或报错。

PHP 接口返回的 JSON 数据结构必须匹配前端图表库要求
多数前端图表库(如 ECharts、Chart.js)对数据格式有明确约定,PHP 后端不能只拼个 json_encode() 就完事。常见错误是返回嵌套过深、字段名不一致、数值类型为字符串、时间戳未转 ISO 格式,导致图表空白或报错 Cannot read property 'x' of undefined。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 先查你用的图表库文档,确认它期望的
series.data是二维数组还是对象数组;ECharts 通常接受[{name: "A", value: 123}]或[[x, y], [x, y]],而 Chart.js 更倾向{labels: [...], datasets: [{data: [...]}]} - PHP 中用
floatval()或强制类型转换(float)$row['amount']处理数据库查出的字符串数值,避免前端typeof data[0].value === "string" - 日期字段若用于横轴,统一转为 ISO 8601 字符串:
date('c', strtotime($row['created_at'])),别传 Unix 时间戳——ECharts 能识别,但 Chart.js 默认不解析数字时间戳 - 接口开头加
header('Content-Type: application/json; charset=utf-8');,防止中文乱码或 MIME 类型错误被浏览器拦截
按需聚合数据,别把原始记录全扔给前端
图表通常展示聚合结果(日活、月销量、TOP5 分类),而非上万条明细。PHP 接口若直接 SELECT * FROM log_table 再用 array_reduce() 在 PHP 层统计,会严重拖慢响应速度,也浪费带宽。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 优先在 SQL 层完成分组与聚合:用
GROUP BY DATE(created_at)统计日数据,SUM(amount)算总量,COUNT(DISTINCT user_id)算去重用户数 - 避免在 PHP 循环里反复调用
date()或strtotime();可先用DATE_FORMAT(created_at, '%Y-%m-%d')在 SQL 中格式化好 - 若需多维度交叉(如“各城市每小时订单量”),用
GROUP BY city, HOUR(created_at),再用 PHP 构建嵌套数组,比前端遍历更可控 - 加缓存:对变化不频繁的数据(如年度汇总),用
apcu_store()或 Redis 缓存查询结果,TTL 设为 3600 秒即可
处理空数据和错误边界,前端才不会白屏
数据库没数据、SQL 报错、权限不足时,如果 PHP 直接返回空响应或 500 错误,前端图表常卡在 loading 或显示“Invalid data”,排查困难。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 统一返回结构体,例如:
{"code": 0, "msg": "success", "data": [...]};错误时code非 0,data可为空数组,前端靠code判断逻辑分支 - SQL 查询前检查必要参数:
if (empty($_GET['type'])) { die(json_encode(['code'=>400, 'msg'=>'missing type'])); } - 用
try...catch包裹 PDO 查询,捕获PDOException并记录日志,不要暴露 SQL 详情给前端 - 空数据时仍返回合法 JSON:
"data": [],而非null或false,避免前端data.map()报错
避免 XSS 和 SQL 注入,图表接口不是后门
图表接口常被忽略安全校验,尤其当支持动态 WHERE 条件(如按时间段筛选)时,直接拼接 $_GET['start_time'] 极易引发注入;返回 HTML 片段或未过滤的用户名还会导致 XSS。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 所有外部输入必须过滤:时间参数用
strtotime()+date()校验合法性,非数字 ID 用filter_var($id, FILTER_VALIDATE_INT) - SQL 条件动态构建时,只允许白名单字段参与:
$allowed_fields = ['status', 'category']; if (!in_array($field, $allowed_fields)) die('invalid field'); - PDO 必须用预处理语句:
$stmt = $pdo->prepare("SELECT * FROM sales WHERE date >= ? AND date execute([$start, $end]); - 若图表需显示用户昵称等可能含 HTML 的字段,输出前用
htmlspecialchars($name, ENT_QUOTES, 'UTF-8')转义
最常被忽略的是时间范围校验——前端传个 start=1970-01-01、end=2100-12-31,后端没限制就全表扫描,数据库瞬间卡死。加一行 if (strtotime($end) - strtotime($start) > 31*86400) die('range too large'); 能省掉大半线上事故。











