經典場景:調試時在 header() 前 echo $url;,結果導致跳轉完全失效,頁面只輸出 URL 字串。根本原因在於 HTTP 協議規定:Header 必須在 Body 之前發送,一旦有任何輸出(含空白、BOM、錯誤訊息),Header 通道即關閉。
Location: url 中冒號後不可有空格,正確寫法 header('Location: https://example.com');<?php 前的空白行、HTML 標籤include/require 的檔案結尾 ?> 後有空白/換行Warning: Cannot modify header information)header() 不會 自動終止腳本,後續代碼仍會跑完,建議搭配 exit;。修改 php.ini:
output_buffering = 4096
; 或 On(內部預設 4096 bytes)
重啟 PHP-FPM/Apache。原理:PHP 將輸出先存入記憶體緩衝區,header() 仍可在緩衝區刷新前插入 Header。
<?php
ob_start(); // 腳本最開頭調用
// ... 任意邏輯、echo、include ...
header('Location: https://example.com');
ob_end_flush(); // 發送緩衝內容並關閉緩衝
exit;
適用於無法修改 php.ini 的虛擬主機、或需精確控制輸出時機的場景。
?>,官方 PSR-12 亦建議如此,杜絕尾部空白輸出。error_reporting(E_ALL); ini_set('display_errors', '0'); 生產環境關閉錯誤顯示,改寫入日誌。<!-- 方案 A:Meta Refresh -->
<meta http-equiv="refresh" content="0;url=https://example.com">
<!-- 方案 B:JavaScript -->
<script>window.location.replace('https://example.com');</script>
缺點:需瀏覽器解析 HTML、JS 執行,較 Header 3xx 跳轉慢,且爬蟲可能不跟隨。僅在無法控制 Header 時使用。
<?php
// 1. 檔案頂部:無 BOM、無空白、無 HTML
declare(strict_types=1); // 可選,嚴格模式
// 2. 業務邏輯
$url = 'https://example.com/target';
// 3. 跳轉前:確認無任何 echo/print/var_dump
// 4. 發送 Header
header('Location: ' . $url, true, 302); // 明確狀態碼
// 5. 立即終止
exit;
ob_start() 會影響效能嗎?exit 也能跳轉?header('Location: ...') 相對路徑可以嗎?