
本文详解如何通过 php 动态生成 morris bar 图的 labels 数组,替代硬编码字符串,确保悬停提示准确显示数据库中的账户名(account),并避免手动拼接 json 导致的格式错误与安全风险。
本文详解如何通过 php 动态生成 morris bar 图的 labels 数组,替代硬编码字符串,确保悬停提示准确显示数据库中的账户名(account),并避免手动拼接 json 导致的格式错误与安全风险。
Morris.js 是一款轻量级、易集成的数据可视化库,常用于快速渲染条形图、折线图等。但在实际开发中,一个常见痛点是:labels 参数需为 JavaScript 字符串数组(如 [‘Alice’, ‘Bob’, ‘Charlie’]),而开发者常误将其设为字段名字符串(如 ‘account’),导致悬停提示失效或显示字段名而非真实值。
问题根源在于原始代码中 labels:’account’ 的写法——这并非合法的 Morris 配置项(labels 应接收数组,而非字符串键名),且 data 数组也因手动拼接 json 字符串存在严重隐患:易产生语法错误(如未转义单引号)、sql 注入风险、中文乱码及 xss 漏洞。
✅ 正确解法是:分离数据结构与标签逻辑,用 json_encode() 安全生成标准 JSON,再由 Morris.js 原生支持的 labels 数组参数消费。
步骤一:优化 SQL 查询,统一字段别名
确保子查询返回的员工姓名字段名为 employee(与 Morris 的 xkey 保持一致),同时保留 account 字段用于标签:
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 -- 注意:原 ORDER BY emp_id ASC 无对应字段,应改为 employee LIMIT 10;
⚠️ 注意:ORDER BY emp_id ASC 在原始 SQL 中引用了不存在的别名 emp_id,已修正为 employee;若需按员工编码排序,请确保子查询中 d.employee_code 可被外层引用,或改用 JOIN 提升可读性与性能。
步骤二:PHP 安全构建数据与标签数组
摒弃字符串拼接,改用关联数组 + json_encode():
<?php $conn = mysqli_connect("localhost", "root", "", "database_name"); $sql = "SELECT ... "; // 上述优化后的 SQL $most_link = mysqli_query($conn, $sql); $data_arr = []; $labels_arr = []; while ($row = mysqli_fetch_assoc($most_link)) { $data_arr[] = $row; // ['account'=>'A001','employee'=>'张三','total'=>24] $labels_arr[] = $row['account']; // ['A001', 'A002', ...] } $data_json = json_encode($data_arr); $labels_json = json_encode($labels_arr); ?>
步骤三:前端 Morris 初始化(关键配置)
在 <script> 中正确注入 JSON 数据,并显式指定 labels:</script>
<div id="most"></div> <script> new Morris.Bar({ element: 'most', data: <?php echo $data_json; ?>, xkey: 'employee', // X 轴显示员工全名(柱状图横坐标) ykeys: ['total'], // Y 轴绑定登录次数 labels: <?php echo $labels_json; ?>, // ✅ 动态悬停标签:显示 account 值 hideHover: 'auto', barColors: ['#F5761A'], // 可选:增强可读性 xLabelAngle: 45, resize: true }); </script>
关键注意事项
- labels 必须是与 data 数组长度一致的字符串数组,顺序严格对应每条数据项;
- xkey(如 ’employee’)控制柱子横坐标文本,labels 控制悬停框顶部标题(即 tooltip header),二者可不同;
- 始终使用 mysqli_fetch_assoc()(非 fetch_array())避免索引混淆;
- 生产环境务必添加错误处理(如 mysqli_connect_error()、mysqli_error($conn));
- 若 account 含特殊字符(如单引号、换行符),json_encode() 自动转义,无需额外处理。
通过此方案,你将获得完全动态、安全可靠且符合 Morris.js 规范的悬停标签系统——既满足业务需求,又筑牢代码质量底线。