本文目录导读:

我来详细介绍PHP项目实现数据统计图表的几种主流方案。
整体实现流程
数据获取 (PHP/MySQL)
→ 数据处理 (数组/JSON)
→ 图表生成 (JS库)
→ 前端展示
主流图表库选择
ECharts (推荐) - 百度开源
// PHP后端 - 准备数据
<?php
// 获取统计数据
$sql = "SELECT DATE(created_at) as date, COUNT(*) as count
FROM orders
GROUP BY DATE(created_at)
ORDER BY date DESC
LIMIT 7";
$result = $db->query($sql);
$data = [];
while($row = $result->fetch_assoc()) {
$data[] = $row;
}
// 返回JSON
header('Content-Type: application/json');
echo json_encode($data);
?>
// 前端 - ECharts图表展示
$.ajax({
url: 'api/getChartData.php',
method: 'GET',
success: function(res) {
var myChart = echarts.init(document.getElementById('chart'));
var dates = res.map(item => item.date);
var counts = res.map(item => parseInt(item.count));
var option = {
xAxis: {
type: 'category',
data: dates
},
yAxis: {
type: 'value'
},
series: [{
data: counts,
type: 'line' // 或 'bar'
}]
};
myChart.setOption(option);
}
});
Chart.js - 轻量级
// PHP输出JSON数据
$chartData = [
'labels' => ['1月', '2月', '3月', '4月'],
'datasets' => [
[
'label' => '销售额',
'data' => [12000, 19000, 15000, 22000],
'backgroundColor' => 'rgba(54, 162, 235, 0.2)'
]
]
];
echo json_encode($chartData);
// Chart.js 渲染
new Chart(document.getElementById('myChart'), {
type: 'bar',
data: <?php echo json_encode($chartData); ?>
});
Highcharts - 商业级
// 生成配置数组
$config = [
'chart' => ['type' => 'column'], => ['text' => '月度销售统计'],
'series' => [
[
'name' => '销售额',
'data' => [5000, 8000, 12000, 15000]
]
]
];
完整示例:销售统计仪表盘
数据库表结构
CREATE TABLE orders (
id INT PRIMARY KEY,
amount DECIMAL(10,2),
created_at DATETIME,
status VARCHAR(20)
);
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(100),
category VARCHAR(50),
price DECIMAL(10,2)
);
PHP后端 - 统计API
<?php
// api/stats.php
class StatisticsController {
// 1. 日销售额统计
public function dailySales() {
$sql = "SELECT DATE(created_at) as date,
SUM(amount) as total,
COUNT(*) as orders
FROM orders
WHERE status = 'completed'
GROUP BY DATE(created_at)
ORDER BY date DESC
LIMIT 30";
// 执行查询...
return $this->formatChartData($result);
}
// 2. 分类销售占比
public function categoryStats() {
$sql = "SELECT p.category,
SUM(o.amount) as total,
COUNT(*) as count
FROM orders o
JOIN products p ON o.product_id = p.id
GROUP BY p.category";
// 执行查询...
return $this->formatPieData($result);
}
// 3. 本月每日趋势
public function monthlyTrend() {
$sql = "SELECT DATE_FORMAT(created_at, '%Y-%m-%d') as day,
SUM(amount) as revenue
FROM orders
WHERE MONTH(created_at) = MONTH(CURDATE())
AND YEAR(created_at) = YEAR(CURDATE())
GROUP BY day";
// 返回前端所需格式
return [
'dates' => array_column($data, 'day'),
'revenue' => array_column($data, 'revenue')
];
}
// 数据格式化辅助函数
private function formatChartData($result) {
$categories = [];
$values = [];
while($row = $result->fetch_assoc()) {
$categories[] = $row['date'];
$values[] = floatval($row['total']);
}
return json_encode([
'categories' => $categories,
'values' => $values
]);
}
}
?>
前端HTML - 完整仪表盘
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
<div class="dashboard">
<!-- 折线图 - 销售趋势 -->
<div id="salesTrend" style="height:400px"></div>
<!-- 饼图 - 分类占比 -->
<div id="categoryPie" style="height:300px"></div>
<!-- 柱状图 - 对比 -->
<div id="comparison" style="height:350px"></div>
</div>
<script>
$(document).ready(function() {
// 初始化图表
initSalesTrend();
initCategoryPie();
initComparison();
});
function initSalesTrend() {
$.getJSON('api/stats.php?action=daily', function(data) {
var chart = echarts.init(document.getElementById('salesTrend'));
chart.setOption({
title: { text: '30天销售趋势' },
tooltip: { trigger: 'axis' },
xAxis: {
type: 'category',
data: data.categories
},
yAxis: {
type: 'value',
axisLabel: {
formatter: '¥{value}'
}
},
series: [{
name: '销售额',
type: 'line',
data: data.values,
smooth: true,
areaStyle: {}
}]
});
});
}
function initCategoryPie() {
$.getJSON('api/stats.php?action=category', function(data) {
var chart = echarts.init(document.getElementById('categoryPie'));
chart.setOption({
title: { text: '分类销售占比' },
series: [{
type: 'pie',
data: data,
radius: ['40%', '70%']
}]
});
});
}
</script>
</body>
</html>
性能优化建议
数据缓存策略
// 使用Redis缓存统计结果
$cacheKey = 'stats_daily_' . date('Ymd');
if ($redis->exists($cacheKey)) {
$data = json_decode($redis->get($cacheKey), true);
} else {
// 执行复杂查询
$data = $this->calculateDailyStats();
$redis->setex($cacheKey, 3600, json_encode($data)); // 缓存1小时
}
大屏实时统计
// WebSocket推送更新
use Ratchet\MessageComponentInterface;
class StatsServer implements MessageComponentInterface {
public function onOpen(ConnectionInterface $conn) {
// 每5秒推送更新
$this->loop->addPeriodicTimer(5, function() use ($conn) {
$stats = $this->getLatestStats();
$conn->send(json_encode($stats));
});
}
}
MySQL查询优化
-- 创建汇总表(物化视图)
CREATE TABLE daily_stats (
date DATE PRIMARY KEY,
total_sales DECIMAL(15,2),
order_count INT,
avg_amount DECIMAL(10,2)
);
-- 定时汇总
INSERT INTO daily_stats
SELECT DATE(created_at),
SUM(amount),
COUNT(*),
AVG(amount)
FROM orders
WHERE created_at >= CURDATE() - INTERVAL 30 DAY
GROUP BY DATE(created_at)
ON DUPLICATE KEY UPDATE
total_sales = VALUES(total_sales),
order_count = VALUES(order_count);
图表库选择建议
| 库 | 适用场景 | 特点 |
|---|---|---|
| ECharts | 企业级、大数据量 | 功能丰富、免费中文文档 |
| Chart.js | 简单图表、移动端 | 轻量级、响应式 |
| Highcharts | 商业项目 | 兼容性好、收费 |
| D3.js | 自定义可视化 | 灵活、学习成本高 |
| AntV | 数据驱动 | 阿里系、多图表类型 |
推荐方案:
- 小型项目:Chart.js + PHP JSON接口
- 中型项目:ECharts + Redis缓存 + MySQL汇总表
- 大型项目:ECharts + WebSocket + 专门统计服务
PHP主要负责数据获取和处理,图表渲染交给前端JS库,这种前后端分离的方式最灵活高效。