PHP/Apache环境下多次调用header()函数失效问题咨询
兄弟,你的思路其实没毛病——正常来说,只要headers_sent()返回false,输出缓冲也开着,最后一次调用header()确实应该覆盖之前的响应头设置。不过结合PHP 5.1.2的那个更新日志,这里可能有几个容易踩的暗坑,咱们一步步捋:
首先得澄清下那个更新日志的准确意思:PHP 5.1.2之后给header()加了第三个$replace参数,默认是true(也就是替换同名字段)。但如果之前的代码里有人用了header('Content-Type: text/html', false)这种写法(第二个参数设为false表示添加而非替换),那后面你再调用默认的header('Content-Type: application/json')可能就不会完全覆盖,反而会出现多个Content-Type头,浏览器有时候会优先取第一个,导致你看到的还是text/html。
那针对你的情况,试试这些解决方案:
强制替换响应头:调用
header()时明确指定第三个参数为true,确保彻底替换掉之前的设置:header('Content-Type: application/json', true);要是连状态码一起设置更稳妥:
header('HTTP/1.1 200 OK'); header('Content-Type: application/json', true);先清掉旧的响应头:在设置新的
Content-Type之前,用header_remove()把之前的Content-Type头清干净:header_remove('Content-Type'); header('Content-Type: application/json');排查隐性的设置点:搜遍你的代码库,看看有没有其他地方(比如框架的中间件、第三方库、甚至是某个被include的文件)偷偷设置了
text/html的Content-Type,而且是在你调用application/json之后的代码——毕竟最后一次生效的前提是你的调用真的是最后一次。禁用PHP默认的MIME类型:有些情况下PHP会自动添加
text/html作为默认响应头,你可以在代码开头先关掉这个设置:ini_set('default_mimetype', '');
另外再确认下输出缓冲的状态,用ob_get_level()看看缓冲层级是不是正常,ob_get_contents()检查下缓冲里有没有意外的空格、换行或者BOM头——这些虽然不会触发headers_sent(),但有时候也会间接影响响应头的处理。
内容的提问来源于stack exchange,提问作者TheStoryCoder

