PHP+Chart.js仪表盘多图表无法同时显示问题求助
仪表盘多图表异常显示问题
问题描述
我在网站上制作了一个包含3种不同可视化图表的仪表盘,数据来源于数据库,当前遇到以下问题:
- 第一个图表可正常显示,但另外两个无法显示;
- 隐藏或删除第一个图表后,第二个图表会显示,但第三个仍无法显示。
截图情况
- 截图1:第一个图表显示,后两个不显示;
- 截图2:删除第一个图表代码后,第二个图表显示;
- 截图3:删除前两个图表后,第三个图表才显示。
现有代码
<!--CHARTS--><!--BAR CHART--><div class="container-fluid px-4"><?php // Attempt select query execution try{ $barsql = "SELECT * FROM castro_rentals.unit"; $barresult = $pdo->query($barsql); if($barresult->rowCount() > 0) { $price = array(); $unit_no = array(); while($row = $barresult->fetch()) { $price[] = $row["price"]; $unit_no[] = $row["unit_no"]; } unset($barresult); } else { echo "No records matching your query were found."; } } catch(PDOException $e){ die("ERROR: Could not able to execute $barsql. " . $e->getMessage()); } // Close connection unset($pdo); ?><div class="card mb-4"> <!--BAR CHART--> <div class="card-header"> <i class="fas fa-chart-bar me-1"></i> Unit Prices </div> <div class="card-body"> <canvas id="myBarChart" width="100%" height="50"></canvas> </div> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> //SETUP BLOCK const price = <?php echo json_encode($price); ?>; const unit_no = <?php echo json_encode($unit_no); ?>; const data = { labels: unit_no, datasets: [{ label: 'Price', data: price, backgroundColor: ['rgba(57, 43, 90, .6)'], borderColor:'rgb(57, 43, 90)', borderWidth: 2 }] }; //CONFIG BLOCK const config = { type: 'bar', data, options: { scales: { y: { beginAtZero: true } } } }; //RENDER BLOCK const myBarChart = new Chart( document.getElementById('myBarChart'), config ); </script> <div class="card-footer small text-muted">Updated yesterday at 11:59 PM</div></div><div class="row"> <div class="col-lg-6"> <!--LINE CHART--> <?php include('config/dbcon.php'); // Attempt select query execution try{ $linesql = "SELECT * FROM castro_rentals.payment"; $lineresult = $pdo->query($linesql); if($lineresult->rowCount() > 0) { $amount = array(); $paymentdate = array(); while($row = $lineresult->fetch()) { $amount[] = $row["amount"]; $paymentdate[] = $row["paymentdate"]; } unset($lineresult); } else { echo "No records matching your query were found."; } } catch(PDOException $e){ die("ERROR: Could not able to execute $linesql. " . $e->getMessage()); } // Close connection unset($pdo); ?> <div class="card mb-4"> <div class="card-header"> <i class="fas fa-chart-line me-1"></i> Monthly Income </div> <div class="card-body"> <canvas id="myLineChart" width="100%" height="50"></canvas> </div> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> //SETUP BLOCK const amount = <?php echo json_encode($amount); ?>; const paymentdate = <?php echo json_encode($paymentdate); ?>; const data = { labels: paymentdate, datasets: [{ label: 'Amount', data: amount, backgroundColor: ['rgba(57, 43, 90, .6)'], borderColor:'rgb(57, 43, 90)', borderWidth: 2 }] }; //CONFIG BLOCK const config = { type: 'line', data, options: { scales: { y: { beginAtZero: true } } } }; //RENDER BLOCK const myLineChart = new Chart( document.getElementById('myLineChart'), config ); </script> <div class="card-footer small text-muted">Updated yesterday at 11:59 PM</div> </div> </div><!--PIE CHART--> <div class="col-lg-6"> <!--PIE CHART--><?php include('config/dbcon.php'); // Attempt select query execution try{ $piesql = "SELECT * FROM castro_rentals.property"; $pieresult = $pdo->query($piesql); if($pieresult->rowCount() > 0) { $propertyname = array(); $paymentdate = array(); while($row = $pieresult->fetch()) { $propertyname[] = $row["propertyname"]; $propertytype[] = $row["propertytype"]; } unset($pieresult); } else { echo "No records matching your query were found."; } } catch(PDOException $e){ die("ERROR: Could not able to execute $piesql. " . $e->getMessage()); } // Close connection unset($pdo); ?> <div class="card mb-4"> <div class="card-header"> <i class="fas fa-chart-pie me-1"></i> # of Property Type </div> <div class="card-body"> <canvas id="myPieChart" width="100%" height="50"></canvas> </div> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> //SETUP BLOCK const propertyname = <?php echo json_encode($propertyname); ?>; const propertytype = <?php echo json_encode($propertytype); ?>; const data = { labels: propertytype, datasets: [{ label: 'propertyname', data: propertyname, backgroundColor: ['rgba(57, 43, 90, .6)'], borderColor:'rgb(57, 43, 90)', borderWidth: 2 }] }; //CONFIG BLOCK const config = { type: 'pie', data, options: { scales: { y: { beginAtZero: true } } } }; //RENDER BLOCK const myPieChart = new Chart( document.getElementById('myPieChart'), config ); </script> <div class="card-footer small text-muted">Updated yesterday at 11:59 PM</div> </div> </div></div>
已尝试的解决方法
调整canvas标签前的div元素(修改、移除、调整尺寸),问题仍未解决。
问题根源
- 重复加载Chart.js:每个图表都独立引入Chart.js库,重复加载会导致库实例冲突,中断后续图表初始化;
- 全局变量冲突:三个图表的JS代码均使用
const data和const config,全局作用域下重复声明const变量会触发语法错误,导致后续脚本停止执行; - PDO连接管理混乱:每个图表查询后销毁PDO连接,再重新引入配置文件重建连接,可能引发连接异常;
- 饼图数据逻辑错误:饼图需要数值型统计数据,但当前代码直接传入
propertyname字符串数组,不符合Chart.js要求,且多余的scales配置会导致渲染异常。
修复方案
1. 统一引入Chart.js
将Chart.js的引入移至页面最顶部,仅加载一次:
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <!-- 后续图表代码不再重复引入 -->
2. 避免全局变量冲突
使用**立即执行函数表达式(IIFE)**包裹每个图表的JS代码,隔离变量作用域:
// 柱状图JS示例 (function() { const price = <?php echo json_encode($price); ?>; const unit_no = <?php echo json_encode($unit_no); ?>; const data = { labels: unit_no, datasets: [{ label: 'Price', data: price, backgroundColor: ['rgba(57, 43, 90, .6)'], borderColor:'rgb(57, 43, 90)', borderWidth: 2 }] }; const config = { type: 'bar', data, options: { scales: { y: { beginAtZero: true } } } }; new Chart(document.getElementById('myBarChart'), config); })();
3. 优化PDO连接逻辑
仅在页面顶部初始化一次PDO连接,所有查询共用该连接,最后统一销毁:
<?php include('config/dbcon.php'); // 仅加载一次连接配置 // 柱状图数据查询 try { $barsql = "SELECT * FROM castro_rentals.unit"; $barresult = $pdo->query($barsql); $price = []; $unit_no = []; if($barresult->rowCount() > 0) { while($row = $barresult->fetch()) { $price[] = $row["price"]; $unit_no[] = $row["unit_no"]; } unset($barresult); } else { echo "No records matching your query were found."; } } catch(PDOException $e) { die("ERROR: Could not execute $barsql. " . $e->getMessage()); } // 折线图数据查询 try { $linesql = "SELECT * FROM castro_rentals.payment"; $lineresult = $pdo->query($linesql); $amount = []; $paymentdate = []; if($lineresult->rowCount() > 0) { while($row = $lineresult->fetch()) { $amount[] = $row["amount"]; $paymentdate[] = $row["paymentdate"]; } unset($lineresult); } else { echo "No records matching your query were found."; } } catch(PDOException $e) { die("ERROR: Could not execute $linesql. " . $e->getMessage()); } // 饼图数据查询(修复统计逻辑) try { // 统计每种物业类型的数量 $piesql = "SELECT propertytype, COUNT(*) as count FROM castro_rentals.property GROUP BY propertytype"; $pieresult = $pdo->query($piesql); $propertyTypes = []; $propertyCounts = []; if($pieresult->rowCount() > 0) { while($row = $pieresult->fetch()) { $propertyTypes[] = $row["propertytype"]; $propertyCounts[] = $row["count"]; } unset($pieresult); } else { echo "No records matching your query were found."; } } catch(PDOException $e) { die("ERROR: Could not execute $piesql. " . $e->getMessage()); } unset($pdo); // 最后统一销毁连接 ?>
4. 修复饼图配置
移除饼图中多余的scales配置,并使用正确的统计数据:
(function() { const propertyTypes = <?php echo json_encode($propertyTypes); ?>; const propertyCounts = <?php echo json_encode($propertyCounts); ?>; const data = { labels: propertyTypes, datasets: [{ label: 'Property Type Count', data: propertyCounts, backgroundColor: [ 'rgba(57, 43, 90, .6)', 'rgba(75, 192, 192, 0.6)', 'rgba(255, 206, 86, 0.6)' ], borderColor: [ 'rgb(57, 43, 90)', 'rgb(75, 192, 192)', 'rgb(255, 206, 86)' ], borderWidth: 2 }] }; const config = { type: 'pie', data, options: {} // 饼图不需要y轴刻度 }; new Chart(document.getElementById('myPieChart'), config); })();
内容的提问来源于stack exchange,提问作者definitelynotaprogrammer
相关产品推荐
相关产品推荐

