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

PHP 中 UTF-8 BOM 導致的頁面渲染異常及解決方案

     編輯:PHP 相關知識

前言:一個被 BOM 坑慘的下午

還記得當年用 Dreamweaver 寫 WordPress 主題時,頁面頂部總莫名其妙多出幾個空白行,CSS 布局全亂套。後來才發現,罪魁禍首竟是「包含 Unicode 簽名 (BOM)」這個默認勾選的小選項。本文將徹底講透 BOM 是什麼、為何會搞壞 PHP 頁面、以及如何在各類編輯器中徹底根治。

什麼是 BOM (Byte Order Mark)?

BOM 全稱 Byte Order Mark,中文稱「字節順序標記」。它是一組位於文本文件最開頭的 2~4 個隱形字節,用於標識:

  • 文件採用 Unicode 編碼(UTF-8/UTF-16/UTF-32)
  • 字節序(大端序 Big-Endian 或小端序 Little-Endian)
編碼BOM 十六進制是否必需說明
UTF-8EF BB BF可選無字節序問題,僅作編碼標識
UTF-16LEFF FE必需小端序
UTF-16BEFE FF必需大端序
UTF-32LEFF FE 00 00必需小端序
UTF-32BE00 00 FE FF必需大端序

Dreamweaver 編碼設置截圖

為什麼 PHP 會「中招」?

PHP 解析器在執行腳本時,會將文件內容原樣輸出到輸出緩衝區。若文件開頭存在 BOM(UTF-8 下為 EF BB BF 三字節),PHP 會將其視為 已輸出內容,導致:

  1. header()、setcookie()、session_start() 等必須在輸出前調用的函數拋出 Cannot modify header information - headers already sent 警告
  2. 頁面頂部出現不可見的空白行,破壞 XML/JSON 輸出、HTML5 Doctype 聲明、CSS/JS 內聯輸出等
  3. 引入文件時,被引入文件的 BOM 同樣會被輸出,污染主文件

歷史註記:PHP 5.3 及之前版本無內建 BOM 過濾機制。PHP 7+ 雖優化了輸出緩衝,但 源文件仍不應包含 BOM,這是 PSR-1/PSR-12 編碼規範的硬性要求。

各主流編輯器/IDE 去除 BOM 設置指南

Dreamweaver (本文起因)

  1. 菜單 修改 → 頁面屬性 → 標題/編碼
  2. 取消勾選 「包括 Unicode 簽名 (BOM)」
  3. 點擊「確定」並保存文件

Visual Studio Code

  • 右下角狀態欄點擊編碼 → 「以編碼保存」 → 選擇 UTF-8(無 BOM),而非 UTF-8 with BOM
  • 或設置 "files.encoding": "utf8"(默認即無 BOM)

PhpStorm / IntelliJ IDEA

  • File → File Encoding → 確保項目編碼為 UTF-8
  • 設置 Settings → Editor → File Encodings → Default encoding for properties files: UTF-8
  • PhpStorm 默認不寫入 BOM,極少踩坑

Sublime Text

  • File → Save with Encoding → 選擇 UTF-8(而非 UTF-8 with BOM)

Notepad++

  • 菜單 編碼 → 選擇「轉為 UTF-8 編碼」(而非「UTF-8-BOM」)
  • 或設置 設置 → 首選項 → 新建文檔 → 編碼: UTF-8 並取消勾選「加上 BOM」

Vim / Neovim

" .vimrc 中設置
set fileencodings=utf-8,ucs-bom,gbk,gb18030
set bomb?     " 查看當前文件是否有 BOM
set nobomb    " 移除 BOM
:w            " 保存即生效

命令行批量檢測與清理 BOM

Linux/macOS 查找含 BOM 文件

# 遞歸查找項目下所有帶 BOM 的 PHP/HTML/JS/CSS 文件
grep -r -l $'^\xEF\xBB\xBF' --include="*.php" --include="*.html" --include="*.js" --include="*.css" .

批量移除 BOM (sed 版)

# 備份後原地修改
find . -type f \( -name "*.php" -o -name "*.html" -o -name "*.js" -o -name "*.css" \) \
  -exec sed -i '1s/^\xEF\xBB\xBF//' {} +

批量移除 BOM (PHP 腳本版,跨平台)

<?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";

最佳實踐總結

  1. 統一編碼規範:團隊約定所有源碼文件 UTF-8 無 BOM,寫入 .editorconfig 強制落地。
  2. root = true [*] charset = utf-8 insert_final_newline = true trim_trailing_whitespace = true # 無 BOM 是默認行為,無需額外配置
  3. CI/CD 門禁:在 Git pre-commit hook 或 CI 流水線加入 BOM 檢測腳本,攔截非規範提交。
  4. 引入文件審計:include/require 的第三方庫若帶 BOM,請向上游反饋或自行打補丁清理。
  5. 輸出緩衝兜底:入口文件最開頭調用 ob_start() 可緩解偶發 BOM 導致的 header 報錯,但治標不治本,務必從源頭杜絕。

結語

BOM 在 UTF-16/32 中是剛需,但在 UTF-8 下純屬多餘,更是 PHP 開發者的「隱形殺手」。養成「無 BOM 保存」的肌肉記憶,配合編輯器配置固化與 CI 門禁,即可徹底告別莫名其妙的空白行與 Header 警告,讓頁面渲染乾淨如初。

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