還記得當年用 Dreamweaver 寫 WordPress 主題時,頁面頂部總莫名其妙多出幾個空白行,CSS 布局全亂套。後來才發現,罪魁禍首竟是「包含 Unicode 簽名 (BOM)」這個默認勾選的小選項。本文將徹底講透 BOM 是什麼、為何會搞壞 PHP 頁面、以及如何在各類編輯器中徹底根治。
BOM 全稱 Byte Order Mark,中文稱「字節順序標記」。它是一組位於文本文件最開頭的 2~4 個隱形字節,用於標識:
| 編碼 | BOM 十六進制 | 是否必需 | 說明 |
|---|---|---|---|
| UTF-8 | EF BB BF | 可選 | 無字節序問題,僅作編碼標識 |
| UTF-16LE | FF FE | 必需 | 小端序 |
| UTF-16BE | FE FF | 必需 | 大端序 |
| UTF-32LE | FF FE 00 00 | 必需 | 小端序 |
| UTF-32BE | 00 00 FE FF | 必需 | 大端序 |

PHP 解析器在執行腳本時,會將文件內容原樣輸出到輸出緩衝區。若文件開頭存在 BOM(UTF-8 下為 EF BB BF 三字節),PHP 會將其視為 已輸出內容,導致:
header()、setcookie()、session_start() 等必須在輸出前調用的函數拋出 Cannot modify header information - headers already sent 警告歷史註記:PHP 5.3 及之前版本無內建 BOM 過濾機制。PHP 7+ 雖優化了輸出緩衝,但 源文件仍不應包含 BOM,這是 PSR-1/PSR-12 編碼規範的硬性要求。
"files.encoding": "utf8"(默認即無 BOM)File → File Encoding → 確保項目編碼為 UTF-8Settings → Editor → File Encodings → Default encoding for properties files: UTF-8File → Save with Encoding → 選擇 UTF-8(而非 UTF-8 with BOM)設置 → 首選項 → 新建文檔 → 編碼: UTF-8 並取消勾選「加上 BOM」" .vimrc 中設置
set fileencodings=utf-8,ucs-bom,gbk,gb18030
set bomb? " 查看當前文件是否有 BOM
set nobomb " 移除 BOM
:w " 保存即生效
# 遞歸查找項目下所有帶 BOM 的 PHP/HTML/JS/CSS 文件
grep -r -l $'^\xEF\xBB\xBF' --include="*.php" --include="*.html" --include="*.js" --include="*.css" .
# 備份後原地修改
find . -type f \( -name "*.php" -o -name "*.html" -o -name "*.js" -o -name "*.css" \) \
-exec sed -i '1s/^\xEF\xBB\xBF//' {} +
<?php
// remove_bom.php - 放項目根目錄執行
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(__DIR__));
foreach ($iterator as $file) {
if ($file->isFile() && in_array($file->getExtension(), ['php','html','js','css','xml','json','txt','md'])) {
$content = file_get_contents($file->getPathname());
if (str_starts_with($content, "\xEF\xBB\xBF")) {
$content = substr($content, 3);
file_put_contents($file->getPathname(), $content);
echo "Removed BOM: {$file->getPathname()}\n";
}
}
}
echo "Done.\n";
.editorconfig 強制落地。root = true
[*]
charset = utf-8
insert_final_newline = true
trim_trailing_whitespace = true
# 無 BOM 是默認行為,無需額外配置
include/require 的第三方庫若帶 BOM,請向上游反饋或自行打補丁清理。ob_start() 可緩解偶發 BOM 導致的 header 報錯,但治標不治本,務必從源頭杜絕。BOM 在 UTF-16/32 中是剛需,但在 UTF-8 下純屬多餘,更是 PHP 開發者的「隱形殺手」。養成「無 BOM 保存」的肌肉記憶,配合編輯器配置固化與 CI 門禁,即可徹底告別莫名其妙的空白行與 Header 警告,讓頁面渲染乾淨如初。