如何修复PHP中的"Headers already sent"错误:分步指南

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

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

开始课程

认识一下:"Headers already sent"——你的新敌人(也是朋友)

\n\n

如果你曾用PHP写过代码,你很可能遇到过这个错误。它突然出现,往往在最不合时宜的时刻——当你几乎完成脚本时。错误信息令人恐惧,红色显示,似乎整个代码都崩溃了。但实际上,这是PHP中最有用的错误之一。它教你正确处理HTTP协议。

\n\n

在本教程中,我们将分析为什么会出现Headers already sent错误,如何诊断它,以及最重要的是,如何一劳永逸地修复它。我们不会简单地从Stack Overflow复制答案——我们将理解其本质。开始吧!

\n\n

什么是HTTP头部以及为什么PHP会报错?

\n\n

在修复之前,需要了解其结构。当PHP向浏览器发送响应时,它分两个阶段进行:

\n\n
    \n
  • 首先——头部(headers)。这是元信息:内容类型(Content-Type)、编码、Cookie、响应状态(200 OK、404 Not Found)。
  • \n
  • 然后——响应体(body)。这是HTML、文本、JSON本身——用户看到的内容。
  • \n
\n\n

问题在于,PHP不能在开始发送响应体之后发送头部。如果你在已经输出了至少一个字符(甚至是一个空格)之后尝试调用header(),PHP会报错:

\n\n
Warning: Cannot modify header information - headers already sent by (output started at /path/to/file.php:12)
\n\n

这就是全部奥秘。这个错误不是致命的——它只是警告你的header()没有生效。但后果可能很严重:重定向不会执行,Cookie不会设置,JSON响应会损坏。

\n\n

导致此问题的五大原因

\n\n

让我们分析最常见的场景。你是否有同感?

\n\n

1. <?php之前的空格或空行

\n\n

这是经典情况。你打开文件,在开始标签<?php之前有一个空格、空行或BOM(字节顺序标记)。PHP将这个字符视为输出的一部分——然后就出问题了。

\n\n
// ❌ 错误:<?php之前有空格\n <?php\nheader('Location: /new-page.php');\n?>
\n\n
// ✅ 正确:<?php之前没有任何字符\n<?php\nheader('Location: /new-page.php');\n?>
\n\n

2. 在header()之前通过echo或print输出

\n\n

这是新手常见但合乎逻辑的错误:先输出一些内容,然后尝试重定向用户。

\n\n
<?php\necho "你好,世界!";\nheader('Location: /thanks.php'); // ❌ 错误:已经输出了内容\n?>
\n\n

3. PHP块之前的HTML代码

\n\n

文件中可能混合了代码:先是HTML标记,然后是带有header()的PHP逻辑。

\n\n
<!DOCTYPE html>\n<html>\n<head>\n    <title>我的网站</title>\n</head>\n<body>\n<?php\nheader('Location: /login.php'); // ❌ 错误:HTML已经发送\n?>\n</body>\n</html>
\n\n

4. PHP错误和var_dump()等函数

\n\n

脚本可能在调用header()之前输出警告或调试信息。例如,如果你启用了display_errors并且PHP输出了警告。

\n\n
<?php\nvar_dump($some_variable); // 输出数据\nheader('Content-Type: application/json'); // ❌ 错误\n?>
\n\n

5. 包含文件(include/require)中的不可见字符

\n\n

你使用include或require包含一个文件,而该文件末尾在关闭标签?>之后有多余的空行或空格。

\n\n
// config.php\n<?php\n$db_host = 'localhost';\n?>\n // ← 这个在?>之后的空格破坏了所有东西!
\n\n

如何找到问题根源:逐步诊断

\n\n

最重要的是——错误总是明确指出输出开始的位置。请仔细阅读错误信息

博客

书籍推荐