
本文详解如何通过 php 动态生成 morris.js 柱状图的 labels 数组,避免硬编码导致的灵活性缺失,确保悬停提示准确显示数据库中的自定义字段(如 account),并提供安全、可维护的 json 数据构造方案。
本文详解如何通过 php 动态生成 morris.js 柱状图的 labels 数组,避免硬编码导致的灵活性缺失,确保悬停提示准确显示数据库中的自定义字段(如 account),并提供安全、可维护的 json 数据构造方案。
Morris Bar 图表的 labels 选项用于定义图例或悬停提示中显示的文本内容。在原始代码中,labels: ‘account’ 实际上是错误用法——Morris.js 的 labels 参数不接受字符串字段名,而应是一个与 data 数组长度一致的字符串数组(例如 [‘UserA’, ‘UserB’, …])。将 ‘account’ 直接赋值给 labels 会导致图表无法正确渲染悬停信息,甚至报错。
正确的做法是:在 PHP 层分离数据主体与标签文本,分别构造合规的 JSON 数组。关键在于两点:
- sql 查询需明确别名,使字段名与前端期望一致(如将子查询结果命名为 employee,而非保留 emp_id);
- 严禁手动拼接 JSON 字符串(如 “{‘key’:'”.$val.”‘}”),极易引发语法错误或 xss 风险;必须使用 json_encode() 保证输出合法、安全。
以下是优化后的完整实现:
<?php $conn = mysqli_connect("localhost", "root", "", "database_name"); // ✅ 修正 SQL:为子查询结果使用语义化别名 'employee',并确保 ORDER BY 使用该别名 $sql = "SELECT account, (SELECT fullname FROM employees AS d WHERE r.emp_id = d.employee_code) AS employee, COUNT(username) AS total FROM logins AS r GROUP BY account ORDER BY employee ASC LIMIT 10"; $most_link = mysqli_query($conn, $sql); if (!$most_link) { die('Query failed: ' . mysqli_error($conn)); } // ✅ 安全构建数据与标签数组 $data_arr = []; $label_arr = []; while ($row = mysqli_fetch_assoc($most_link)) { $data_arr[] = $row; // 包含 account, employee, total 的关联数组 $label_arr[] = $row['account']; // 动态提取 account 作为悬停标签 } // ✅ 使用 json_encode() 输出标准 JSON,自动处理引号、转义与编码 $json_data = json_encode($data_arr); $json_labels = json_encode($label_arr); ?> <script> new Morris.Bar({ element: 'most', data: <?php echo $json_data; ?>, xkey: 'employee', // X 轴显示员工姓名 ykeys: ['total'], // Y 轴绑定 total 字段 labels: <?php echo $json_labels; ?>, // ✅ 动态标签数组,如 ["ACC-001", "ACC-002"] hideHover: 'auto', barColors: ['#F5761A'], // 可选:增强可读性 xLabelAngle: 45, resize: true }); </script>
⚠️ 重要注意事项:
- 永远不要手动拼接 JSON:原始代码中 $most_sold .= “{ accounnt:’…’}” 存在严重隐患——若 account 值含单引号、换行或 Unicode 字符,将直接破坏 JavaScript 语法。json_encode() 是唯一可靠方案。
- 字段名一致性:SQL 中 AS employee 必须与 xkey: ’employee’ 严格匹配;同理,$row[‘account’] 必须与数据库实际列名一致。
- 错误处理:添加 mysqli_query 错误检查,避免静默失败。
- 字符集安全:确保数据库连接使用 UTF-8(mysqli_set_charset($conn, ‘utf8mb4’)),防止中文等字符乱码。
通过此方案,图表悬停时将精准显示每个柱子对应的 account 值(如 ACC-001),同时保持代码健壮性与可维护性。Morris.js 虽已停止维护,但该数据构造原则适用于所有基于 JSON 的前端图表库(如 Chart.js、ApexCharts),核心逻辑始终是:后端交付结构清晰、格式合规的 JSON,前端专注可视化逻辑。