如何修复 PHP 中的 "Headers already sent":完整指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:“你已经向屏幕输出了内容,我无法操作了”

\n

如果你曾经在自己的网站上看到过白屏,上面显示着令人恐惧的消息 Warning: Cannot modify header information - headers already sent,那么你并不孤单。这也许是初学者(以及不仅仅是初学者)PHP 开发者中最常见的错误之一。在 Stack Overflow 上,这个问题获得了数十万次浏览,而全球范围内错误代码的副本数量更是以 TB 计。

\n

但好消息是,“Headers already sent” 错误并非诅咒,而只是 PHP 给出的一个严格提醒:“嘿,你已经开始发送 HTML 代码了,现在却想修改 HTTP 标头。这是不允许的!”

\n

在本文中,我们将详细分析 为什么 PHP 中会出现 headers already sent 错误,如何找到它,以及最重要的是,如何一劳永逸地修复它。开始吧!

\n\n

1. 什么是 HTTP 标头,为什么它们“已经发送”?

\n

在深入代码之前,让我们用通俗易懂的方式了解一下“幕后”发生了什么。当 PHP 脚本执行时,它首先向浏览器发送 HTTP 标头 (header)。这些标头包含元信息:内容类型 (Content-Type)、Cookie (Set-Cookie)、重定向 (Location)、响应状态码 (200, 404, 301) 等等。

\n

只有在 所有 标头发送之后,才开始发送文档的主体——即你在页面上看到的 HTML。PHP 只允许在发送第一个字节的内容之前修改标头。

\n

一旦你向屏幕输出了任何内容(通过 echo、print、var_dump,甚至只是在 <?php 之前有一个空格),PHP 就会认为标头已经发送。在此之后任何调用 header()、setcookie() 或 session_start() 的尝试都会导致致命错误。

\n\n

1.1. 错误的经典示例

\n
<?php\necho "你好,世界!";\n// 哎呀!我们已经输出了内容。\nheader("Location: https://example.com");\n// Warning: Cannot modify header information - headers already sent\n?>
\n

在这个例子中,echo 将文本发送到了文档主体。之后,PHP 无法覆盖标头来进行重定向。这完全合乎逻辑。

\n\n

2. 导致 "Headers already sent" 的五大原因

\n

该错误不仅可能由显式的 echo 引起。以下是即使是有经验的开发者也会遇到的最常见场景:

\n
    \n
  • <?php 之前的空格或空行 — 最常见的“bug”。如果文件中在开始标签之前至少有一个空格,它就会被发送到输出中。
  • \n
  • 不可见的 BOM(字节顺序标记)字符 — 文件以 UTF-8 with BOM 编码保存。前 3 个字节 (EF BB BF) 被视为输出。
  • \n
  • 来自包含文件的输出 — 在 config.php 文件中,?> 之后有多余的空格。
  • \n
  • 错误和警告 — 如果 PHP 输出了一个警告(例如,关于使用未定义的变量),这也会被视为发送内容。
  • \n
  • 在 header() 之前的 print、printf、var_dump 函数 — 任何输出函数都会破坏标头。
  • \n
\n\n

3. 如何找到问题根源:3 种方法

\n

在修复之前,需要找到“多余”输出来自哪里。使用以下方法之一。

\n\n

3.1. 开启所有错误显示

\n

在脚本开头(任何输出之前)添加:

\n
<?php\nerror_reporting(E_ALL);\nini_set('display_errors', 1);\n?>
\n

PHP 通常会显示发生输出的确切行号。查找类似 Output started at /path/to/file.php:12 的消息。

\n\n

3.2. 使用 error_get_last() 函数

\n

可以捕获最后一个错误

博客

书籍推荐