如何在Chart.js折线图中动态展示截至今日的近两年SQL数据
解决方案:动态生成近24个月的支出数据与图表
我来帮你搞定这个动态时间范围的需求,核心思路是用日期类自动计算近24个月的区间,彻底摆脱固定自然年的限制,同时简化代码结构:
一、重构PHP数据获取逻辑
我们可以利用PHP的DateTime类动态生成近24个月的时间节点,统一查询每个月的数据,不用再分开处理去年和今年:
<?php $conn = new mysqli(blah blah blah); if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } // 初始化当前日期,计算起始时间(往前推24个月) $currentDate = new DateTime(); $startDate = (clone $currentDate)->sub(new DateInterval('P24M')); $monthlyData = []; $chartLabels = []; // 遍历近24个月 for ($i = 0; $i < 24; $i++) { // 计算当前循环对应的月份 $targetMonth = (clone $startDate)->add(new DateInterval("P{$i}M")); $year = $targetMonth->format('Y'); $month = $targetMonth->format('n'); // 数字格式的月份(1-12) // 生成图表标签(例如:Feb 2023) $chartLabels[] = $targetMonth->format('M Y'); // 用预处理语句查询当月支出,更安全防注入 $sql = "SELECT SUM(Contracts.Sum_Approved) AS total FROM Contracts JOIN Budgets ON Contracts.Budget = Budgets.BudgetID WHERE MONTH(Contracts.Decision_Date) = ? AND YEAR(Contracts.Decision_Date) = ? AND Contracts.owner = ? AND Contracts.Archived = 0 AND Contracts.Budget = ?"; $stmt = $conn->prepare($sql); $stmt->bind_param("iiii", $month, $year, $userid, $budget); $stmt->execute(); $result = $stmt->get_result(); $row = $result->fetch_array(); // 处理空数据,避免null导致图表异常 $monthlyData[] = $row['total'] ?? 0; } // 清理资源 $stmt->close(); $conn->close(); ?>
优化亮点:
- 用
DateTime自动计算时间区间,完全不用手动判断年份月份,适配任意当前日期 - 预处理语句替代字符串拼接,提升代码安全性
- 把标签和数据统一存入数组,后续直接传递给Chart.js,砍掉了一堆冗余的单个月份变量
二、简化Chart.js配置
现在直接把PHP生成的数组传入Chart.js,不用再手动拼接24个数据项:
var ctx = document.getElementById("myAreaChart"); var myLineChart = new Chart(ctx, { type: 'line', data: { labels: <?php echo json_encode($chartLabels); ?>, datasets: [{ label: "Agreed Funding", lineTension: 0.3, backgroundColor: "rgba(78, 115, 223, 0.05)", borderColor: "rgba(78, 115, 223, 1)", pointRadius: 3, pointBackgroundColor: "rgba(78, 115, 223, 1)", pointBorderColor: "rgba(78, 115, 223, 1)", pointHoverRadius: 3, pointHoverBackgroundColor: "rgba(78, 115, 223, 1)", pointHoverBorderColor: "rgba(78, 115, 223, 1)", pointHitRadius: 10, pointBorderWidth: 2, data : <?php echo json_encode($monthlyData); ?>, }], }, options: { maintainAspectRatio: false, layout: { padding: { left: 10, right: 25, top: 25, bottom: 0 } }, scales: { xAxes: [{ time: { unit: 'month' }, // 改为month更贴合我们的按月统计维度 gridLines: { display: true, drawBorder: false }, ticks: { maxTicksLimit: 7 } }], yAxes: [{ ticks: { maxTicksLimit: 5, padding: 10, callback: function(value, index, values) { return '£' + number_format(value); } }, gridLines: { color: "rgb(234, 236, 244)", zeroLineColor: "rgb(234, 236, 244)", drawBorder: false, borderDash: [2], zeroLineBorderDash: [2] } }], }, legend: { display: false }, tooltips: { backgroundColor: "rgb(255,255,255)", bodyFontColor: "#858796", titleMarginBottom: 10, titleFontColor: '#6e707e', titleFontSize: 14, borderColor: '#dddfeb', borderWidth: 1, xPadding: 15, yPadding: 15, displayColors: false, intersect: false, mode: 'index', caretPadding: 10, callbacks: { label: function(tooltipItem, chart) { var datasetLabel = chart.datasets[tooltipItem.datasetIndex].label || ''; return datasetLabel + ': £' + number_format(tooltipItem.yLabel); } } } } });
配置调整说明:
- 用
json_encode直接把PHP数组转成JS数组,代码简洁不易出错 - 调整
xAxes.time.unit为month,让图表的时间轴渲染更准确 - 自动适配动态生成的时间范围,不管今天是几月,都会展示最近24个月的完整数据
这样调整后,你的图表就会自动展示从当前日期往前推24个月到当前月的所有支出数据,完全实现动态的近两年范围,而且代码结构更清晰、安全,没有繁琐的条件判断。
内容的提问来源于stack exchange,提问作者user5838014
相关产品推荐
相关产品推荐

