在處理報表資料時,交叉表(Pivot Table)是將原始資料依照行、列維度進行聚合分析的常用手段。若直接用 SQL 撰寫動態交叉查詢,不僅語法複雜,維護成本也極高。本文介紹一個輕量級的 PHP 類別 Pivot,能將二維陣列資料快速轉換為交叉表,支援橫向/縱向小計、多種輸出格式,適合中小型專案快速整合。
Pivot 類別封裝了初始化、資料填充、合計計算與渲染輸出四大流程,主要屬性如下:
$data:輸入資料集(二維關聯陣列)$topPivot:作為列標題的欄位名$leftPivot:作為行標題的欄位名$measure:需聚合計算的數值欄位$horizontalColumn / $verticalColumn:去重後的行、列標題集合$pivotValue:核心儲存結構 [$row][$col] = value$isHorizontalTotal / $isVerticalTotal:是否啟用橫向/縱向小計private function InitPivot() {
foreach ($this->data as $d) {
$this->horizontalColumn[] = $d[$this->leftPivot];
$this->verticalColumn[] = $d[$this->topPivot];
}
$this->horizontalColumn = array_unique($this->horizontalColumn);
$this->verticalColumn = array_unique($this->verticalColumn);
// 預填 0,確保每個交叉點皆有值
foreach ($this->horizontalColumn as $h) {
foreach ($this->verticalColumn as $v) {
$this->pivotValue[$h][$v] = 0;
}
}
}
此方法掃描資料集,取出所有唯一的行、列標題,並預先建立完整的矩陣骨架,避免後續填值時出現「未定義索引」錯誤。
private function fillData() {
foreach ($this->data as $row) {
$this->pivotValue[$row[$this->leftPivot]][$row[$this->topPivot]] += $row[$this->measure];
}
if ($this->isHorizontalTotal) $this->setHorizontalTotal();
if ($this->isVerticalTotal) $this->setVerticalTotal();
}
透過累加方式將度量值填入對應交叉點,再依設定呼叫小計計算。
$verticalColumn 尾端加入 total 欄,逐行累加各列數值。$horizontalColumn 尾端加入 total 列,逐列累加各行數值。// 直接輸出陣列結構(除錯用)
function Render() {
echo '';
print_r($this->pivotValue);
}
// 輸出 HTML 表格
function RenderToTable() {
$html = "\n";
$html .= "{$this->title} \n";
foreach ($this->verticalColumn as $v) $html .= "$v \n";
$html .= " \n";
foreach ($this->horizontalColumn as $h) {
$html .= "$h \n";
foreach ($this->pivotValue[$h] as $val) $html .= "$val \n";
$html .= " \n";
}
$html .= "
";
return $html;
}
$data = [
['region' => 'North', 'product' => 'A', 'sales' => 100],
['region' => 'North', 'product' => 'B', 'sales' => 200],
['region' => 'South', 'product' => 'A', 'sales' => 150],
['region' => 'South', 'product' => 'B', 'sales' => 250],
];
$pivot = new Pivot($data, 'product', 'region', 'sales');
$pivot->title = '銷售交叉表';
echo $pivot->RenderToTable();
| 銷售交叉表 | A | B | total |
|---|---|---|---|
| North | 100 | 200 | 300 |
| South | 150 | 250 | 400 |
| total | 250 | 450 | 700 |
Pivot 類別以「預建骨架 + 累加填值」的策略,將複雜的交叉邏輯封裝為可重複使用的元件。若專案需求較複雜(如多層維度、動態欄位),可在此基礎上擴充;對於固定維度的報表需求,它已足夠輕量且高效。