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

PHP 中 header() 函數設定 HTTP 狀態碼完整對照表與應用指南

     編輯:PHP 相關知識

在 PHP 開發中,正確使用 header() 函數發送 HTTP 狀態碼是建構 RESTful API、處理重定向、錯誤回應等場景的基礎技能。本文整理了 HTTP/1.1 規範中常見的狀態碼,並提供一個可直接在專案中使用的封裝函數,幫助開發者快速查找並正確應用。

為什麼需要正確設定 HTTP 狀態碼?

HTTP 狀態碼是伺服器與客戶端(瀏覽器、API 消費者、爬蟲)溝通的關鍵語言。正確的狀態碼能:

  • 讓瀏覽器正確處理重定向(301/302/307)
  • 讓 API 消費者依據狀態碼判斷請求結果(200/201/400/401/404/500 等)
  • 利於 SEO:搜尋引擎爬蟲依賴 301 永久移轉、404 不存在等狀態碼建立索引
  • 避免安全風險:例如 403 Forbidden 比 200 OK 配合錯誤訊息更安全

常用 HTTP 狀態碼分類速查

1xx 資訊回應

狀態碼名稱說明
100Continue客戶端應繼續發送請求主體
101Switching Protocols伺服器同意切換協議(如 WebSocket 升級)

2xx 成功

狀態碼名稱典型使用場景
200OK通用成功回應,GET/PUT/PATCH 成功
201CreatedPOST 建立資源成功,配合 Location 標頭
202Accepted非同步處理已接受,尚未完成
204No Content成功但無回應主體(如 DELETE 成功)
206Partial Content範圍請求成功(斷點續傳、影音串流)

3xx 重定向

狀態碼名稱關鍵差異
301Moved Permanently永久移轉,搜尋引擎會傳遞權重,瀏覽器會快取
302Found暫時重定向,HTTP/1.0 行為,POST 可能變 GET
303See Other強制 GET 重定向,PRG 模式常用
304Not Modified快取有效,配合 ETag/Last-Modified
307Temporary Redirect暫時重定向,保持原請求方法(HTTP/1.1)

4xx 客戶端錯誤

狀態碼名稱典型場景
400Bad Request請求語法錯誤、參數驗證失敗
401Unauthorized未認證或 Token 失效
403Forbidden已認證但權限不足
404Not Found資源不存在
405Method Not AllowedHTTP 方法不支援,需回應 Allow 標頭
409Conflict資源衝突(如重複建立)
410Gone資源永久刪除,比 404 更明確
422Unprocessable Entity語意錯誤(WebDAV/RFC 4918),API 驗證失敗常用
429Too Many Requests速率限制,配合 Retry-After

5xx 伺服器錯誤

狀態碼名稱說明
500Internal Server Error未預期的伺服器錯誤
501Not Implemented功能未實作
502Bad Gateway上游伺服器回應無效
503Service Unavailable暫時無法服務(維護、過載),建議加 Retry-After
504Gateway Timeout上游伺服器逾時

可直接使用的 PHP 封裝函數

<?php
/**
 * 發送 HTTP 狀態碼標頭
 * @param int $code HTTP 狀態碼
 * @param string $version HTTP 版本,預設 HTTP/1.1
 * @return void
 */
function send_http_status(int $code, string $version = 'HTTP/1.1'): void
{
    static $messages = [
        100 => 'Continue', 101 => 'Switching Protocols',
        200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information',
        204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content',
        300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found',
        303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect',
        400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden',
        404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable',
        407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict',
        410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed',
        413 => 'Payload Too Large', 414 => 'URI Too Long', 415 => 'Unsupported Media Type',
        416 => 'Range Not Satisfiable', 417 => 'Expectation Failed', 422 => 'Unprocessable Entity',
        429 => 'Too Many Requests',
        500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway',
        503 => 'Service Unavailable', 504 => 'Gateway Timeout',
    ];

    if (!isset($messages[$code])) {
        // 未定義的狀態碼預設 500
        $code = 500;
    }

    // 避免重複發送標頭
    if (headers_sent($file, $line)) {
        error_log("Headers already sent in $file:$line, cannot send status $code");
        return;
    }

    header("$version $code {$messages[$code]}", true, $code);
}

// 使用範例
// send_http_status(404);           // 404 Not Found
// send_http_status(201);           // 201 Created
// send_http_status(301);           // 301 Moved Permanently
// send_http_status(429);           // 429 Too Many Requests
?>

進階應用技巧

1. RESTful API 統一錯誤格式

<?php
function api_error(int $code, string $message, array $errors = []): never
{
    send_http_status($code);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode([
        'success' => false,
        'error' => [
            'code' => $code,
            'message' => $message,
            'details' => $errors,
        ],
    ], JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
    exit;
}

// 使用
// api_error(422, '驗證失敗', ['email' => '格式不正確']);
// api_error(404, '找不到指定資源');
?>

2. 重定向最佳實踐

<?php
function redirect(string $url, int $code = 302): never
{
    // 合法重定向碼:301, 302, 303, 307, 308
    $allowed = [301, 302, 303, 307, 308];
    if (!in_array($code, $allowed, true)) {
        $code = 302;
    }
    send_http_status($code);
    header("Location: $url", true, $code);
    // 兼容舊瀏覽器
    echo "<a href='$url'>Redirecting...</a>";
    exit;
}

// 永久移轉(SEO 友善)
// redirect('https://example.com/new-url', 301);

// POST 後重定向(PRG 模式),防止重複提交
// redirect('/success', 303);
?>

3. 快取控制與 304 Not Modified

<?php
function cache_control(int $maxAge = 3600, bool $mustRevalidate = true): void
{
    $directives = ["max-age=$maxAge"];
    if ($mustRevalidate) $directives[] = 'must-revalidate';
    header('Cache-Control: ' . implode(', ', $directives));
    header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $maxAge) . ' GMT');
}

function check_etag(string $etag): bool
{
    $clientEtag = $_SERVER['HTTP_IF_NONE_MATCH'] ?? '';
    if ($clientEtag === $etag) {
        send_http_status(304);
        return true;
    }
    header("ETag: $etag");
    return false;
}

// 使用範例
// $etag = md5_file($filePath);
// if (check_etag($etag)) exit;
// cache_control(86400);
// readfile($filePath);
?>

常見錯誤與避坑指南

  1. 標頭已發送錯誤:確保在任何輸出(echo、空白、BOM)之前呼叫 header()。使用 headers_sent() 檢測。
  2. 狀態碼與標頭不匹配:header('Location: ...', true, 302) 第三參數必須與狀態碼一致。
  3. 缺少 Content-Type:API 回應務必加 header('Content-Type: application/json; charset=utf-8')。
  4. 重定向迴圈:檢查重定向目標是否再次重定向回原 URL。
  5. 404 濫用:資源永久刪除應用 410 Gone,語意更清晰。
  6. 總結

    掌握 HTTP 狀態碼的正確使用,能讓你的 PHP 應用程式更符合 Web 標準、更易於除錯、對 SEO 更友善、API 介接更順暢。建議將上述封裝函數納入專案共用函式庫,統一管理標頭輸出,減少人為錯誤。

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