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

PHP 實現文章上一篇/下一篇導航:基於 ID 鄰近查詢的最佳實踐

     編輯:PHP 綜合知識

核心邏輯:拒絕 ID±1,擁抱鄰近查詢

許多教程使用 id+1/id-1 實現上下篇,但文章 ID 常因刪除而不連續。正確做法:查詢比當前 ID 小的最大 ID(上一篇)與比當前 ID 大的最小 ID(下一篇)。

SQL 查詢策略

-- 上一篇:ID < 當前,按 ID 降序取第一條
SELECT * FROM article WHERE id < $current_id ORDER BY id DESC LIMIT 1;

-- 下一篇:ID > 當前,按 ID 升序取第一條
SELECT * FROM article WHERE id > $current_id ORDER BY id ASC LIMIT 1;

完整封裝函數

..., 'title'=>..., 'url'=>...]
 */
function getAdjacentArticle($type, $table, $catid = 0, $id) {
    $conn = getDbConnection(); // 你的資料庫連接函數
    
    $where = "id " . ($type === 'pre' ? '<' : '>') . " " . (int)$id;
    if ($catid) $where .= " AND catid = " . (int)$catid;
    
    $order = $type === 'pre' ? 'DESC' : 'ASC';
    $sql = "SELECT id, title FROM {$table} WHERE {$where} ORDER BY id {$order} LIMIT 1";
    
    $result = $conn->query($sql);
    if (!$result || $result->num_rows === 0) return false;
    
    $row = $result->fetch_assoc();
    return [
        'id' => $row['id'],
        'title' => $row['title'],
        'url' => "article.php?id={$row['id']}" . ($catid ? "&catid={$catid}" : '')
    ];
}

// 使用範例
$currentId = (int)($_GET['id'] ?? 0);
$catId = (int)($_GET['catid'] ?? 0);

$prev = getAdjacentArticle('pre', 'article', $catId, $currentId);
$next = getAdjacentArticle('next', 'article', $catId, $currentId);

// 前端輸出
echo '
'; if ($prev) { echo ''; } else { echo '← 上一篇:已是第一篇'; } if ($next) { echo ''; } else { echo '下一篇:已是最新篇 →'; } echo '
';

進階優化:單查詢同時獲取上下篇

利用 UNION 減少資料庫往返:

function getPrevNextSingleQuery($table, $catid, $id) {
    $conn = getDbConnection();
    $catSql = $catid ? "AND catid = " . (int)$catid : "";
    
    $sql = "
        (SELECT 'pre' AS type, id, title FROM {$table} WHERE id < {$id} {$catSql} ORDER BY id DESC LIMIT 1)
        UNION
        (SELECT 'next' AS type, id, title FROM {$table} WHERE id > {$id} {$catSql} ORDER BY id ASC LIMIT 1)
    ";
    
    $result = $conn->query($sql);
    $data = ['pre' => false, 'next' => false];
    while ($row = $result->fetch_assoc()) {
        $data[$row['type']] = [
            'id' => $row['id'],
            'title' => $row['title'],
            'url' => "article.php?id={$row['id']}" . ($catid ? "&catid={$catid}" : '')
        ];
    }
    return $data;
}

緩存策略:減少重複查詢

文章內容頁訪問頻率高,上下篇關係相對固定,適合緩存:

function getCachedAdjacent($table, $catid, $id) {
    $cacheKey = "article_nav_{$table}_{$catid}_{$id}";
    $cached = apcu_fetch($cacheKey); // 或 Redis/Memcached
    if ($cached) return $cached;
    
    $data = getPrevNextSingleQuery($table, $catid, $id);
    apcu_store($cacheKey, $data, 3600); // 緩存 1 小時
    return $data;
}

// 文章更新/刪除時清理相關緩存
function clearArticleNavCache($table, $catid, $id) {
    // 清理當前文章及鄰近文章的緩存
    $ids = [$id];
    // 可選:查詢實際鄰近 ID 並一併清理
    foreach ($ids as $targetId) {
        apcu_delete("article_nav_{$table}_{$catid}_{$targetId}");
    }
}

前端體驗優化

常見陷阱避坑指南

錯誤做法問題正確做法
id-1 / id+1ID 不連續導致 404 或錯誤文章鄰近查詢 ORDER BY id LIMIT 1
未加分類過濾跨分類跳轉,用戶體驗斷層加 catid 條件或提供「全站/分類」切換
每次請求都查庫高併發下資料庫壓力大APCu/Redis 緩存,更新時失效
標題過長撐破佈局移動端顯示異常CSS text-overflow: ellipsis 截斷

總結

  • 核心 SQL:WHERE id < ? ORDER BY id DESC LIMIT 1(上一篇)
  • 單查詢 UNION 獲取雙向導航,效能最優
  • 緩存機制必備,文章變更時主動失效
  • 前端交互細節決定用戶留存體驗

正確實現上下篇導航,不僅解決 ID 不連續問題,更能通過緩存優化顯著降低資料庫負載,是內容型網站必備的基礎功能優化點。

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