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

BOM (Byte Order Mark) 導致 PHP "headers already sent" 錯誤的排查與解決

     編輯:PHP 綜合知識

經典錯誤: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 標頭已送出。

排查步驟

  1. 在 setcookie() 前加入 ob_start()、ob_get_clean() 捕獲輸出,發現為空字串 → 無顯性輸出。
  2. 用十六進位編輯器(或 xxd file.php | head)檢視檔案開頭,發現 EF BB BF。
  3. Vim 中輸入 :set nobomb 移除 BOM,或另存為「UTF-8 無 BOM」。

什麼是 BOM?

  • Byte Order Mark:Unicode 標準標記位元組序(大端/小端)。
  • UTF-8 不需指示位元組序,但 Windows 記事本等工具習慣加入 BOM。
  • PHP 解析器不會忽略 BOM,視為輸出內容。

解決方案

編輯器/工具移除 BOM 方法
VS Code右下角編碼選單 → "Save with Encoding" → "UTF-8"(非 UTF-8 with BOM)
PhpStormFile → 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//' {} \;

預防機制

  • 專案規範:所有 PHP 檔案必須為 UTF-8 無 BOM。
  • .editorconfig 設定:charset = utf-8、insert_final_newline = true。
  • CI 流程加入檢查腳本:
#!/bin/bash
# check-bom.sh
files=$(grep -rl $'\xEF\xBB\xBF' --include="*.php" .)
if [ -n "$files" ]; then
    echo "以下檔案含有 BOM:"
    echo "$files"
    exit 1
fi

補充:output_buffering 緩衝可暫時繞過但非根治

php.ini: output_buffering = On 可吸收 BOM 輸出,但會掩蓋其他「過早輸出」問題,且增加記憶體佔用,不建議依賴。

總結

BOM 是隱形殺手,導致 headers already sent、session_start() 失敗、API 回傳 JSON 前綴雜訊。養成「UTF-8 無 BOM」儲存習慣,配合編輯器設定與 CI 檢查,徹底杜絕。

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