
本文详解如何通过 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,前端专注可视化逻辑。










