首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 單字段多列顯示:數據庫單欄數據橫向分頁佈局的多種實現方案

     編輯:PHP 相關知識

在開發會員列表、標簽雲、商品屬性值展示等場景時,常需將數據庫單一字段的記錄按「每行 N 列、多行」的網格佈局輸出。本文提供從傳統分頁查詢到現代數組分塊的多種方案,並分析性能與適用場景。

場景定義

  • 數據表:employees (id, name)
  • 需求:每行顯示 10 個名字,複選框 + 名稱,自動換行
  • 總記錄數不固定,需動態計算行數

方案一:傳統 LIMIT 分頁查詢(原文思路,不推薦)

<?php
// 缺點:多次查詢、N+1 問題、代碼冗長
$perRow = 10;

// 第一行
$result = mysqli_query($conn, "SELECT name FROM employees ORDER BY id LIMIT 0, {$perRow}");
echo '';
while ($row = mysqli_fetch_assoc($result)) {
    echo ' ' . $row['name'] . '';
}
echo '';

// 後續行
$total = mysqli_num_rows(mysqli_query($conn, "SELECT id FROM employees"));
$rows = ceil($total / $perRow);

for ($k = 1; $k < $rows; $k++) {
    $offset = $k * $perRow;
    $result = mysqli_query($conn, "SELECT name FROM employees ORDER BY id LIMIT {$offset}, {$perRow}");
    echo '';
    while ($row = mysqli_fetch_assoc($result)) {
        echo ' ' . $row['name'] . '';
    }
    echo '';
}

痛點分析

  • 執行 1 + ceil(total/perRow) 次查詢,大數據下極慢
  • 代碼重複,維護困難
  • 無法靈活調整列數(需修改 SQL 和循環邏輯)

方案二:一次查詢 + 數組分塊(推薦,標準做法)

<?php
// 1. 一次性查詢所有需要的數據
$stmt = $pdo->query("SELECT id, name FROM employees ORDER BY id");
$employees = $stmt->fetchAll(PDO::FETCH_ASSOC);

// 2. 配置參數
$colsPerRow = 10;

// 3. 使用 array_chunk 分塊(核心技巧)
$rows = array_chunk($employees, $colsPerRow);

// 4. 輸出
echo '';
foreach ($rows as $rowIndex => $rowData) {
    echo '';
    foreach ($rowData as $emp) {
        echo '';
    }
    // 最後一行不足補空單元格(可選,保持表格對齊)
    $emptyCols = $colsPerRow - count($rowData);
    if ($emptyCols > 0) {
        echo str_repeat('', $emptyCols);
    }
    echo '';
}
echo '
'; echo ''; echo ' ' . htmlspecialchars($emp['name']); echo ' 
';

核心函數:array_chunk

array_chunk(array $array, int $length, bool $preserve_keys = false): array
// 將數組分割為多個長度為 $length 的塊,返回二維數組

方案三:生成器流式處理(超大數據集,內存友好)

<?php
function fetchEmployeesChunked(PDO $pdo, int $chunkSize = 1000): Generator
{
    $offset = 0;
    $pageSize = 1000;
    
    while (true) {
        $stmt = $pdo->prepare("SELECT id, name FROM employees ORDER BY id LIMIT :offset, :limit");
        $stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
        $stmt->bindValue(':limit', $pageSize, PDO::PARAM_INT);
        $stmt->execute();
        
        $batch = $stmt->fetchAll(PDO::FETCH_ASSOC);
        if (empty($batch)) break;
        
        foreach ($batch as $row) {
            yield $row;
        }
        $offset += $pageSize;
    }
}

// 使用:邊讀邊輸出,不佔用大量內存
$colsPerRow = 10;
$buffer = [];

echo '';
foreach (fetchEmployeesChunked($pdo) as $emp) {
    $buffer[] = $emp;
    
    if (count($buffer) === $colsPerRow) {
        echo '';
        foreach ($buffer as $e) {
            echo '';
        }
        echo '';
        $buffer = [];
    }
}

// 處理最後不足一行的數據
if (!empty($buffer)) {
    echo '';
    foreach ($buffer as $e) {
        echo '';
    }
    echo str_repeat('', $colsPerRow - count($buffer));
    echo '';
}
echo '
' . htmlspecialchars($e['name']) . '
' . htmlspecialchars($e['name']) . ' 
';

方案四:CSS Grid / Flex 佈局(現代前端方案,後端只輸出扁平列表)

後端:輸出簡單列表

<?php
$stmt = $pdo->query("SELECT id, name FROM employees ORDER BY id");
$employees = $stmt->fetchAll(PDO::FETCH_ASSOC);

echo '
'; foreach ($employees as $emp) { echo ''; } echo '
';

前端 CSS:自適應多列

.employee-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 12px;
    padding: 16px;
}

.employee-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    background: #fafafa;
    border: 1px solid #eee;
    border-radius: 6px;
    cursor: pointer;
    transition: all 0.2s;
}

.employee-item:hover {
    background: #f0f7ff;
    border-color: #3b82f6;
}

.employee-item input[type="checkbox"] {
    width: 16px;
    height: 16px;
    accent-color: #3b82f6;
}

優勢對比

| 方案 | 後端複雜度 | 前端靈活性 | 響應式支持 | 適用場景 | |------|------------|------------|------------|----------| | 表格 + array_chunk | 低 | 低 | 差 | 固定列數、打印導出 | | 生成器流式 | 中 | 低 | 差 | 萬級以上數據、內存受限 | | **CSS Grid (推薦)** | **極低** | **高** | **優** | **現代 Web 應用、移動端適配** |

進階:動態列數配置

<?php
// 根據屏幕寬度或用戶偏好動態調整(AJAX 載入時傳參)
$colsPerRow = (int)($_GET['cols'] ?? 10);
// 限制範圍
$colsPerRow = max(3, min(20, $colsPerRow));

總結

  1. 避免多次 LIMIT 查詢 — 一次查詢 + array_chunk 是服務端渲染標準解法
  2. 大數據用生成器 — 邊讀邊輸出,內存 O(1)
  3. 現代項目優先 CSS Grid — 後端只輸出語義化列表,佈局交給 CSS,響應式零成本
  4. XSS 防護 — 輸出用戶數據務必 htmlspecialchars()

選對方案,單字段多列顯示從「麻煩的邏輯題」變成「一行代碼的配置事」。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved