认识一下:"Headers already sent"——你的新敌人(也是朋友)
\n\n如果你曾用PHP写过代码,你很可能遇到过这个错误。它突然出现,往往在最不合时宜的时刻——当你几乎完成脚本时。错误信息令人恐惧,红色显示,似乎整个代码都崩溃了。但实际上,这是PHP中最有用的错误之一。它教你正确处理HTTP协议。
\n\n在本教程中,我们将分析为什么会出现Headers already sent错误,如何诊断它,以及最重要的是,如何一劳永逸地修复它。我们不会简单地从Stack Overflow复制答案——我们将理解其本质。开始吧!
什么是HTTP头部以及为什么PHP会报错?
\n\n在修复之前,需要了解其结构。当PHP向浏览器发送响应时,它分两个阶段进行:
\n\n- \n
- 首先——头部(headers)。这是元信息:内容类型(
Content-Type)、编码、Cookie、响应状态(200 OK、404 Not Found)。 \n - 然后——响应体(body)。这是HTML、文本、JSON本身——用户看到的内容。 \n
问题在于,PHP不能在开始发送响应体之后发送头部。如果你在已经输出了至少一个字符(甚至是一个空格)之后尝试调用header(),PHP会报错:
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\n1. <?php之前的空格或空行
\n\n这是经典情况。你打开文件,在开始标签<?php之前有一个空格、空行或BOM(字节顺序标记)。PHP将这个字符视为输出的一部分——然后就出问题了。
// ❌ 错误:<?php之前有空格\n <?php\nheader('Location: /new-page.php');\n?>\n\n// ✅ 正确:<?php之前没有任何字符\n<?php\nheader('Location: /new-page.php');\n?>\n\n2. 在header()之前通过echo或print输出
\n\n这是新手常见但合乎逻辑的错误:先输出一些内容,然后尝试重定向用户。
\n\n<?php\necho "你好,世界!";\nheader('Location: /thanks.php'); // ❌ 错误:已经输出了内容\n?>\n\n3. 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\n4. PHP错误和var_dump()等函数
\n\n脚本可能在调用header()之前输出警告或调试信息。例如,如果你启用了display_errors并且PHP输出了警告。
<?php\nvar_dump($some_variable); // 输出数据\nheader('Content-Type: application/json'); // ❌ 错误\n?>\n\n5. 包含文件(include/require)中的不可见字符
\n\n你使用include或require包含一个文件,而该文件末尾在关闭标签?>之后有多余的空行或空格。
// config.php\n<?php\n$db_host = 'localhost';\n?>\n // ← 这个在?>之后的空格破坏了所有东西!\n\n如何找到问题根源:逐步诊断
\n\n最重要的是——错误总是明确指出输出开始的位置。请仔细阅读错误信息