ob_start() 的核心作用是避免“Headers already sent”错误,确保 header("Location: ...") 稳定生效;它通过输出缓冲拦截提前输出,为响应头发送创造安全环境。

PHP 7.4 中用 ob_start() 配合 header("Location: ..."),核心作用是避免“Headers already sent”错误,让重定向稳定生效。它不改变重定向逻辑,而是为 header() 创造安全的执行环境。
为什么需要 ob_start() 才能重定向
HTTP 协议要求响应头(如 Location)必须在任何正文内容之前发送。PHP 7.4 默认行为是:一旦有 echo、print、HTML 输出、甚至文件开头/结尾的空格或 BOM 字节,就会立即向客户端发送这部分内容——此时再调用 header() 就会失败,并报错 “Cannot modify header information”。ob_start() 把所有这些本该立刻发出的内容先拦下来,存在内存里,等你准备好头信息后再统一处理。
标准写法与关键顺序
必须严格按以下顺序操作:
-
第一行就调用
ob_start()—— 放在<?php后立即执行,前面不能有任何字符(包括空行、UTF-8 BOM) - 中间可自由输出内容(调试
echo、包含模板、执行业务逻辑等) - 调用
header("Location: target.php")—— 此时无输出干扰,必然成功 - 紧跟
exit;或die();—— 防止后续代码继续执行并意外输出 - 最后用
ob_end_flush();发送缓冲区内容(但重定向时浏览器会忽略正文,所以这步实际可省;若需兼容某些代理或调试,可保留)
常见踩坑点(PHP 7.4 特别注意)
这些在 PHP 7.4 中依然高频出现:
立即学习“PHP免费学习笔记(深入)”;
- BOM 头问题:用 Notepad++ 或 VS Code 保存 PHP 文件时,选“UTF-8 无 BOM”编码,否则隐藏的 EF BB BF 字节会被当作输出
-
包含文件带空行:被
include或require的配置文件、函数库,末尾多了一个换行或空格,就会触发错误 -
错误开启 display_errors:开发时若
display_errors = On,PHP 错误警告本身也是输出,会破坏 header 前提;建议用日志记录而非页面显示 -
混淆
ob_end_clean()和ob_end_flush():重定向不需要输出页面内容,用ob_end_clean()更干净;但清理前必须已调用ob_start(),且不能重复开启未关闭的缓冲
一个安全可用的登录跳转示例
以下代码在 PHP 7.4 环境中可稳定运行:
<?php
ob_start(); // 必须第一句
session_start();
if ($_POST['user'] === 'admin' && $_POST['pass'] === '123') {
$_SESSION['logged_in'] = true;
header("Location: dashboard.php");
exit; // 终止执行,防止下方 echo 被输出
}
// 下面只是页面逻辑,不会影响 header
echo "<html><body><p>登录失败,请重试</p></body></html>";
ob_end_clean(); // 清掉上面 echo 的内容,不发给浏览器
?>



















