PHP中headers_sent($filename, $linenum)函数使用方法及无法获取响应头发送位置的问题
PHP中headers_sent($filename, $linenum)函数使用方法及无法获取响应头发送位置的问题
嘿,我来帮你捋清楚这个头疼的问题~ 你遇到的headers_sent($filename, $linenum)返回空文件名和行号0的情况,大多是因为触发响应头发送的输出是在PHP代码执行之前就产生的,PHP没法追踪到这个位置的具体信息。
为什么会出现空文件名和行号0?
最常见的几个原因:
- UTF-8 BOM头问题:很多编辑器默认会给UTF-8编码的文件添加BOM头(三个不可见的特殊字符),它会在PHP开始执行代码之前就被输出到浏览器,直接触发响应头发送。因为这是在PHP代码执行前的操作,PHP自然没法记录对应的文件和行号。
- PHP标签前的隐式输出:如果你的PHP文件(或者引入的其他文件)中,
<?php起始标签前面有空格、换行、甚至是不小心输入的HTML内容,这些内容会被当作普通输出直接发送,同样会触发响应头,而且因为在PHP代码块之外,PHP也无法定位具体的行号。 - 极少数情况是服务器配置自动发送了响应头,但这种情况非常少见,优先排查代码文件本身的问题。
解决和排查步骤
- 检查文件开头的BOM和空白:
打开你的PHP文件,确保<?php是文件的第一个字符,前面没有任何空格、换行。同时在编辑器中开启“显示不可见字符”的选项,查看是否有BOM标识(通常显示为),如果有,将文件重新保存为无BOM的UTF-8编码。 - 排查所有引入的文件:
如果你的代码里使用了include/require引入其他文件,一定要检查这些文件的开头,它们同样可能存在BOM、空白或者提前输出的问题。 - 用输出缓冲辅助调试:
在代码的最开头添加输出缓冲函数,暂时拦截所有输出,这样你就能看到到底是什么内容提前触发了响应头:<?php ob_start(); // 开启输出缓冲 // 这里放你原本的代码内容 // 检查缓冲区内的提前输出 $pre_output = ob_get_contents(); if (!empty($pre_output)) { echo "提前输出的内容:" . htmlspecialchars($pre_output); exit; } // 继续原本的响应头检查逻辑 if (!headers_sent($filename, $linenum)) { header('Location: http://www.example.com/'); exit; } else { echo "Headers already sent in $filename on line $linenum\n" . "Cannot redirect, for now please click this <a " . "href=\"http://www.example.com\">link</a> instead\n"; exit; }
关于headers_sent函数的正确使用
你代码里对headers_sent($filename, $linenum)的调用是正确的——这两个参数是引用传递,PHP会自动将响应头发送的位置信息填充进去,但只有当触发响应头的是PHP代码执行过程中的显式输出(比如echo、print,或者引入文件中的PHP代码输出)时,才能拿到准确的文件和行号。如果是代码执行前的隐式输出,就会出现你遇到的空文件名和0行号的情况。
内容来源于stack exchange
相关产品推荐
相关产品推荐

