PHP 模板輸出莫名其妙出現空行、頂部空白、甚至導致 header() 失效、Session 無法啟動,是開發者常遇到的「玄學」問題。根因通常集中在三點:UTF-8 BOM 頭、包含文件多餘換行、輸出緩衝區控制不當。本文提供系統性排查與徹底解決方案。
| 現象 | 常見根因 | 核心機制 |
|---|---|---|
| 頁面頂部空出 10px 左右 | 多個 UTF-8 文件含 BOM,IE 將多個 BOM 渲染為換行 | BOM = EF BB BF,PHP 直接輸出不解析 |
header() 警告「headers already sent」 | 文件開頭/結尾有空白、換行、或 include 文件輸出 | 任何實際輸出(含空白)會發送 HTTP 標頭 |
| 模板嵌套導致重複空行 | 多層 include 疊加 BOM/換行 | 同上 |
grep -r $'\xEF\xBB\xBF' . --include="*.php" --include="*.html"在入口文件最頂部(<?php 之前無任何字符)啟用緩衝,模板輸出前清理,輸出後刷新:
<?php
// 入口文件最頂部
ob_start();
// 業務邏輯...
require 'header.php'; // 可能含 BOM/空白
// 模板輸出前:清理之前的所有輸出(含 BOM、空白)
ob_end_clean();
// 正式模板輸出
require 'template.php';
// 輸出結束:刷新緩衝區到瀏覽器
ob_end_flush();
?>
原理:ob_start()捕獲所有輸出;ob_end_clean()丟棄捕獲內容並關閉緩衝,此後輸出直接發送給瀏覽器,實現「切除頭部雜質」。
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Language" content="zh-CN" />
<title>頁面標題</title>
<!-- 其他 meta -->
</head>
關鍵:<meta charset> 必須在 <title> 之前,否則 IE 可能誤判編碼導致空白頁。
<?php
// 部署前執行,掃描項目 BOM 文件
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(__DIR__));
foreach ($files as $file) {
if ($file->isFile() && in_array($file->getExtension(), ['php', 'html', 'css', 'js'])) {
$content = file_get_contents($file->getPathname());
if (str_starts_with($content, "\xEF\xBB\xBF")) {
echo "BOM detected: " . $file->getPathname() . PHP_EOL;
}
}
}
?>
<?php 前無任何字符(含空行)ob_start() / ob_end_clean() 兜底<meta charset> 放在 <title> 前short_open_tag=Off 避免衝突「空白輸出」本質上是「過早輸出」。統一編碼規範 + 緩衝區兜底 = 徹底告別空行困擾。