Byte Order Mark (BOM) 是位於 UTF-8 編碼檔案開頭的三個隱藏位元組(EF BB BF),雖然用於標示編碼順序,但在 PHP 執行環境中常導致「Headers already sent」錯誤、輸出異常空白、Session 啟動失敗等棘手問題。本文提供完整的偵測與自動移除解決方案。
header()、session_start()、setcookie() 失效並拋出警告include/require)時產生非預期輸出<?php
/**
* 檢查並選擇性移除檔案的 UTF-8 BOM 標記
*
* @param string $filename 目標檔案路徑
* @param bool $autoRemove true=自動移除並覆寫檔案, false=僅回報狀態
* @return string 處理結果訊息
*/
function checkAndRemoveBOM($filename, $autoRemove = false) {
if (!is_file($filename) || !is_readable($filename)) {
return "錯誤:檔案不存在或不可讀取 - $filename";
}
$content = file_get_contents($filename);
if (strlen($content) < 3) {
return "檔案過小,無 BOM 標記";
}
// 檢查前三個位元組是否為 EF BB BF
$bom = substr($content, 0, 3);
if ($bom === "\xEF\xBB\xBF") {
if ($autoRemove) {
$cleanContent = substr($content, 3);
$bytesWritten = file_put_contents($filename, $cleanContent);
if ($bytesWritten !== false) {
return "✅ 已偵測並自動移除 BOM:$filename (移除 3 位元組)";
}
return "❌ BOM 移除失敗,寫入錯誤:$filename";
}
return "⚠️ 偵測到 BOM 標記:$filename (未自動移除)";
}
return "✅ 未發現 BOM:$filename";
}
// 使用範例
echo checkAndRemoveBOM(__DIR__ . '/config.php', true); // 自動移除模式
echo checkAndRemoveBOM(__DIR__ . '/index.php', false); // 僅檢查模式
?>
針對整個專案進行遞迴掃描:
<?php
function scanProjectBOM($dir, $autoRemove = false) {
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS)
);
$results = ['bom_found' => [], 'clean' => [], 'errors' => []];
foreach ($iterator as $file) {
if ($file->isFile() && in_array($file->getExtension(), ['php', 'html', 'css', 'js', 'json', 'xml', 'csv'])) {
$msg = checkAndRemoveBOM($file->getPathname(), $autoRemove);
if (strpos($msg, 'BOM') !== false && strpos($msg, '未發現') === false) {
$results['bom_found'][] = $msg;
} elseif (strpos($msg, '未發現') !== false) {
$results['clean'][] = $file->getPathname();
} else {
$results['errors'][] = $msg;
}
}
}
return $results;
}
// 執行掃描(謹慎使用自動移除,建議先備份)
$report = scanProjectBOM(__DIR__ . '/../application', true);
print_r($report);
?>
| 編輯器/IDE | 設定路徑 | 關鍵選項 |
|---|---|---|
| VS Code | Settings → Files: Encoding | 勾選「UTF-8 without BOM」或將 files.encoding 設為 utf8 |
| PhpStorm | File → File Encoding | 專案預設選 UTF-8,取消勾選「Add BOM」 |
| Sublime Text | File → Save with Encoding | 選擇 UTF-8(非 UTF-8 with BOM) |
| Notepad++ | 編碼(E) → 選 UTF-8 (無 BOM) | 設定 → 偏好設定 → 新建文檔 → 編碼選 UTF-8 且勾選「不加 BOM」 |
BOM 問題看似微小,實則是 PHP 開發中極常見的隱形殺手。建立「編輯器統一設定 + 專案定期掃描 + 部署前自動檢查」的三層防線,能從根源杜絕此類問題。