經典錯誤:Cannot modify header information - headers already sent by ...,明明 setcookie() 前無任何 echo、空白、HTML,卻仍報錯。罪魁禍首往往是檔案開頭隱藏的 UTF-8 BOM (EF BB BF)。
<?php
// 檔案以 UTF-8 with BOM 儲存
setcookie('test', 'value'); // 錯誤:headers already sent
?>
瀏覽器實際接收到:EF BB BF<?php ...,三個 BOM 位元組被視為輸出內容,導致 HTTP 標頭已送出。
setcookie() 前加入 ob_start()、ob_get_clean() 捕獲輸出,發現為空字串 → 無顯性輸出。xxd file.php | head)檢視檔案開頭,發現 EF BB BF。:set nobomb 移除 BOM,或另存為「UTF-8 無 BOM」。| 編輯器/工具 | 移除 BOM 方法 |
|---|---|
| VS Code | 右下角編碼選單 → "Save with Encoding" → "UTF-8"(非 UTF-8 with BOM) |
| PhpStorm | File → File Encoding → Remove BOM |
| Notepad++ | Encoding → Convert to UTF-8(非 UTF-8-BOM) |
| Vim | :set nobomb 然後 :w |
| 命令列批次 | find . -name "*.php" -exec sed -i '1s/^\xEF\xBB\xBF//' {} \; |
.editorconfig 設定:charset = utf-8、insert_final_newline = true。#!/bin/bash
# check-bom.sh
files=$(grep -rl $'\xEF\xBB\xBF' --include="*.php" .)
if [ -n "$files" ]; then
echo "以下檔案含有 BOM:"
echo "$files"
exit 1
fi
php.ini: output_buffering = On 可吸收 BOM 輸出,但會掩蓋其他「過早輸出」問題,且增加記憶體佔用,不建議依賴。
BOM 是隱形殺手,導致 headers already sent、session_start() 失敗、API 回傳 JSON 前綴雜訊。養成「UTF-8 無 BOM」儲存習慣,配合編輯器設定與 CI 檢查,徹底杜絕。