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

PHP header() 函數深度詳解:HTTP 狀態碼、重定向、緩存控制、文件下載與常見陷阱

     編輯:PHP 相關知識

函數原型

header(string $header, bool $replace = true, int $response_code = 0): void
  • $replace:true 替換同類 Header(預設),false 允許多個同名 Header
  • $response_code:強制設置 HTTP 響應碼(PHP 4.3+)

核心原則:必須在輸出之前調用

<?php
// ❌ 錯誤:前面有空白/HTML/BOM
echo " "; 
header('Location: /'); // Warning: Cannot modify header information

// ✅ 正確:無任何輸出前調用
header('Location: /');
exit;

解決方案:啟用 output_buffering(php.ini 或 ob_start()),或確保文件無 BOM、無前置輸出。

HTTP 狀態碼分類與常用值

類別碼含義典型場景
1xx100Continue大文件上傳預檢
101Switching ProtocolsWebSocket 升級
2xx200OK成功響應
201CreatedPOST 創建資源
204No ContentDELETE 成功無內容
3xx301Moved Permanently永久重定向(SEO 傳遞權重)
302Found臨時重定向(預設 Location 行為)
304Not Modified緩存驗證(配合 ETag/Last-Modified)
307Temporary Redirect保持方法重定向
308Permanent Redirect保持方法永久重定向
4xx400Bad Request參數錯誤
401Unauthorized未登錄/Token 無效
403Forbidden無權限
404Not Found資源不存在
422Unprocessable Entity驗證失敗(WebDAV/RFC 4918)
429Too Many Requests限流
5xx500Internal Server Error代碼異常
502Bad Gateway上游服務失敗
503Service Unavailable維護/過載

實戰場景代碼庫

1. 重定向(最常用)

<?php
// 302 臨時重定向(預設)
header('Location: https://example.com/login');
exit;

// 301 永久重定向(SEO 友好)
header('Location: https://example.com/new-url', true, 301);
exit;

// 相對路徑轉絕對(HTTP/1.1 要求絕對 URI)
$base = "https://{$_SERVER['HTTP_HOST']}" . dirname($_SERVER['PHP_SELF']);
header("Location: {$base}/target.php");
exit;

2. 禁用緩存(動態內容/API 必備)

<?php
// 完整禁用緩存組合拳
header('Cache-Control: no-cache, no-store, must-revalidate, max-age=0'); // HTTP/1.1
header('Pragma: no-cache'); // HTTP/1.0 兼容
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // 過去日期

// 僅驗證緩存(配合 ETag)
header('Cache-Control: no-cache, must-revalidate');
header('ETag: "' . md5($content) . '"');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');

3. 文件下載

<?php
$file = '/path/to/report.xlsx';
$filename = '報表_2024.xlsx';

if (!is_file($file)) {
    http_response_code(404);
    exit('文件不存在');
}

$size = filesize($file);
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment; filename="' . rawurlencode($filename) . '"; filename*=UTF-8\'\'' . rawurlencode($filename));
header('Content-Length: ' . $size);
header('Accept-Ranges: bytes');
header('Cache-Control: private, max-age=0'); // 私有緩存,不經代理
readfile($file); // 高效輸出大文件
exit;

4. API 響應標準化

<?php
function jsonResponse(array $data, int $code = 200): void
{
    http_response_code($code);
    header('Content-Type: application/json; charset=utf-8');
    header('X-Content-Type-Options: nosniff'); // 防 MIME 嗅探
    echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

// 使用
jsonResponse(['status' => 'ok', 'data' => $users]);
jsonResponse(['error' => '驗證失敗'], 422);

5. CORS 跨域頭

<?php
// 簡單請求
header('Access-Control-Allow-Origin: https://app.example.com'); // 不要用 * 配合 credentials
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
header('Access-Control-Max-Age: 86400'); // 預檢緩存 1 天

// 預檢請求直接返回
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(204);
    exit;
}

6. 安全相關頭

<?php
header('X-Frame-Options: DENY'); // 禁止 iframe 嵌入
header('X-Content-Type-Options: nosniff'); // 禁用 MIME 嗅探
header('Referrer-Policy: strict-origin-when-cross-origin');
header('Content-Security-Policy: default-src \'self\'; script-src \'self\' https://cdn.example.com; style-src \'self\' \'unsafe-inline\';');
header('Strict-Transport-Security: max-age=31536000; includeSubDomains; preload'); // 僅 HTTPS

特殊 Header 行為

  • Location: 自動發送 302(除非已發送 3xx),必須配合 exit 防止後續代碼執行。
  • HTTP/1.1 XXX 格式:直接設置狀態行,header('HTTP/1.1 404 Not Found')。
  • 多值 Header:header('Set-Cookie: a=1', false); header('Set-Cookie: b=2', false);($replace=false)。

常見陷阱與避坑

陷阱症狀解決
BOM/空白輸出Warning: Cannot modify header文件存為 UTF-8 無 BOM;ob_start();檢查 include 文件
重定向後代碼繼續執行邏輯錯誤、多次重定向header('Location:...'); exit;
中文文件名下載亂碼瀏覽器顯示亂碼rawurlencode() + filename*=UTF-8'' (RFC 5987)
緩存頭未生效瀏覽器仍緩存檢查代理/CDN 緩存設置;確保 HTTPS 下 HSTS 不衝突
多次 session_start() 導致 Header 衝突Cookie 重複用 session_status() 判斷

現代框架中的對應

  • Laravel: response()->json(), redirect(), download(), 中間件自動處理 CORS/安全頭
  • Symfony: Response 物件、HttpFoundation 組件
  • Slim/PSR-7: $response->withHeader()、withStatus()

精通 header() 的各類 HTTP 交互細節,是構建健壯 Web 應用、API、文件服務、安全防護的基石。始終記住:Header 先於 Body,狀態碼語義化,緩存策略顯式化,安全頭標準化。

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