搜尋
首頁後端開發php教程解决 PHP "headers already sent" 错误

这篇文章是 stackoverflow 上的一个问题的回答,答案集中了其它答案的想法,并做了归纳,所以翻译过来,以后遇到 “headers already sent” 的错误就可以直接一一排查,或者干脆在代码动手及设计上避免这类问题了。

发送 header 前不要有任何输出

发送或者修改 HTTP 头信息的方法必须在任何输出被输出之前被调用。否则调用将会出错:

Warning: Cannot modify header information - headers already sent ( output started at script:line)

这些方法可以修改(modify) HTTP 头信息:

  • header / header_remove
  • session_start / session_regenerate_id
  • setcookie / setrawcookie

输出(output)可以是:

  • 无意的:
    • 之后的空格
    • UTF-8 BOM
  • 有意的:
    • print , echo 以及其他能产生输出的方法
    • 区块

为什么这个错误会产生

为了理解为什么 HTTP header 必须在输出之前发送出去,我们有必要了解看一下一个典型的 HTTP 相应。PHP 脚本主要用来生成 HTML ,但它也会发送一系列的 HTTP/CGI 头信息到 web 服务器:

HTTP/1.1 200 OKPowered-By: PHP/5.3.7Vary: Accept-EncodingContent-Type: text/html; charset=utf-8<html><head><title>PHP page output page</title></head><body><h1 id="Content">Content</h1> <p>Some more output follows...</p>and <a href="/"> <img  src=internal-icon-delayed alt="解决 PHP "headers already sent" 错误" > </a>

页面或者输出总是紧跟在头信息后面。PHP 必须先把头信息发送给 web 服务器,并且它只能发送一次,在这之后就再也不能修改头信息了。

当 PHP 第一次接收到输出时( print , echo , ) 它会清掉所有收集到的头信息。在此之后它能把输出所有想输出的内容,但是再想发送 HTTP 头信息就不可能了。

怎么找到到底是哪里提前产生了输出?

header() 头信息包含所有与问题产生相关的信息:

Warning: Cannot modify header information - headers already sent by (output started at /www/usr2345/htdocs/auth.php:52) in /www/usr2345/htdocs/index.php on line 100

在上面的警告中, line 100 指向调用 header() 失败的脚本行数。

圆括号里的 output started 这条信息更加重要。它指出了先于 header() 前的输出的源头。在这个例子中是 auth.php 的 第 52 行,这就是你要去找的过早的输出的地方。

典型的原因有这些:

  1. print, echo

    有意的 print 和 echo 语句输出将会中断输出 HTTP 头信息的机会。应用程序流必须重组以避免这种行为,可以使用 function 和模版来重组,从而保证 header() 调用是在信息被写出之前。

    产生输出的方法包括:

    • print, echo, printf, vprintf
    • trigger_error, ob_flush, ob_end_flush, var_dump, print_r
    • readfile, passthru, flush, imagepng, imagejpeg

    以及其他用户自定义的方法。

  2. 原始的 HTML

    在一个 PHP 文件中未被解析的 HTML 区块也是输出。脚本中各种可能触发调用 header() 的条件都必须在任何 区块前声明。

  3. 如果警告指向第 1 行的输出,那么它很有可能指向的是在

     <?php// 在 <?php 前有个空格

同样它可能出现在附加的脚本或者脚本区块上:

?><?php

PHP 确实在闭合标签后占据了一个换行符,但是它不会在上面的空白处插入换行符、制表符或者空格(也就是说这是我们自己造成的)。

  1. UTF-8 BOM

    换行符或者空格可能导致问题,但是不可见的字符序列同样可以。最著名的就是大多数文本编辑器并不会显示的 UTF-8 BOM 。它是在 UTF-8 编码的文档里可选甚至是多余的,被标示为 EF BB BF 的字节序列。但是 PHP 必须把它当作原始的输出来处理。它可能以  这样的符号输出(如果客户端以 Latin-1 来解释这个文档)或者其他这样的“非法输出”。

    以某种图形化的编辑器或者基于 JAVA 的 IDE 查看这类文件时,你可能察觉不到 UTF-8 BOM 的存在。它们没有把 UTF-8 BOM 形象化(受制于 Unicode 标准)。然而大多数程序编辑器和控制台编辑程序会这样处理:

    像这样就能简单地提早发现问题了。其他的编辑器在设置某些选项后也能纠正这样的问题(Windows 上的 Notepad++ 可以识别并且 纠正 BOM 问题 ),另一个发现 BOM 的方法就是借助十六进制的编辑器。在 *nix 系统上,大都提供了 hexdump ,如果没有的话,其他图形化的变种也可以用来简化审计这些问题的步骤:

    一个简单的修正方法就是将文本编辑器设置为 以 UTF-8 (no BOM) 保存文件save files as UTF-8 (no BOM) )或者其他类似的设置。

    修正程序

    有很多自动化的工具可以检测并修改文本文件( sed / awk 或者 recode )。PHP 里有 phptags 。它可以把打开标签和关闭标签重写成长标签(

    phptags  --whitespace  *.php

同样,你可以在某个目录或整个项目目录使用这个命令。

  1. ?> 后的空白

    如果错误代码在闭合标签 >? 这一行的前面,那么这就是 >? 后的空格或者原始文本输出导致的问题。PHP 的结束标记并不会在遇到闭合标签时终止执行脚本,任何 ?> 之后的文本或者空格字符都会被当作页面内容输出。

    通用的被鼓励的做法,特别是针对新手,是避免在 PHP 文件后加上闭合标签 ?> 。这样就能避免一部分产生这类问题的情况。

  2. 错误源提示:”Unknown on line 0”

    如果没有给出具体的错误源,那么这就是典型的 PHP 扩展或者 php.ini 设置的问题:

    • 偶尔是 gzip 编码设置或者是 ob_gzhandler
    • 也有可能是 php.ini 设置里模块加载了两次导致 PHP 产生了启动 / 警告信息
  3. 先前的错误导致输出了错误信息

    如果前面的 PHP 语句或者表达式造成了 warning 或者 notice 信息导致输出,这些输出也被认为是过早地输出。

    在这种情况下你需要避免错误,推后这些语句的执行,或者抑制这些信息的输出,可以使用 isset() 进行判断,或者使用抑制符 @ ,前提是它们不会阻止后续的调试。

没有错误信息输出

如果你禁用了 php.ini 里的 error_reporting 或者 display_errors 设置,那么将不会产生 warning 。但是忽略错误并不会让问题消失,头信息仍然不能在过早的输出输出之前发送出去。

所以当 header("Location: ...") 跳转静默地失败时,建议你去查看 warnings 。在脚本的最前面用下面的两条命令重新开启错误报告设置:

error_reporting(E_ALL);ini_set("display_errors", 1);

或者如果其他的设置都失败了那就设置 set_error_handler("var_dump"); 。

至于跳转的 header ,在执行至最后的代码时你应该遵循下面的这种风格:

exit(header("Location: /finished.html"));

最好是提供一个方法,特别是当 header() 执行失败时打印出用户信息。

变通方法:输出缓冲

PHP 的输出缓冲的方法是缓解这种问题的一种变通方法。它运行起来可靠,但是你绝不要使用它来替代你架构良好应用程序结构,从控制逻辑中分离输出。它的真实目的是用来减轻大块数据传输至服务器时的压力。

  1. output_buffering 设置 在 php.ini 或者 .htaccess 或者甚至在最新的 FPM/FastCGI 的 .user.ini 中设置;
  2. 同样你可以在脚本的最前面使用 ob_start() 来设置,但是它并没那么可靠:
    • 即使 在第一个脚本里,空格或者 BOM 也有可能在此之前被输出
    • 它可以隐藏 HTML 输出里的空格(将空格放到 buffer 中),但是只要应用程序逻辑企图发送二进制内容(比如生成的图片),缓冲里的无关的输出就会成为问题(这样 ob_clean() 方法就成为下一步的变通方法了)。
    • 缓冲有大小限制,并且在默认配置下很容易超出,并且这种情况并不少见,一旦发生也不太容易追踪。

因此这两个方法变得不可靠了,特别是当你需要更改开发环境或者生产环境的配置的时候。这就是为什么输出缓冲被认为只是一种蹩脚的变通方法。

建议参考官方手册里的基本 使用方法 ,以及它的优缺点:

  • 输出缓冲是什么
  • 为什么使用 output buffering
  • 使用输出缓冲是不好的实践吗?
  • 正确使用 output buffering 解决 “header already sent” 的例子

但是在其他的服务器上是好的?

如果你之前没有收到过头信息的 warning ,那么 php.ini 里的 output_buffering 设置改变了。在现在的/不同的服务器上很有可能没有设置。

使用 headers_sent() 检查

你可以使用 headers_sent 来检查是否可以发送头信息。这种方法可以有效地检查以便输出一个错误信息或是应用其他的逻辑。

不错的回退变通方法有:

  • HTML tag

    如果你的应用程序很难在结构上解决这个问题,有个简单但显得不专业的做法是在 HTML

    标签中来跳转网页。可以这样实现:

    <meta http-equiv="Location" content="http://example.com/">

    或者加上一个延迟时间

    <meta http-equiv="Refresh" content="2; url=../target.html">

  • JavaScript 跳转

    另一个可选的方法就是使用 JavaScript 跳转 来实现网页跳转:

    <script> location.replace("target.html"); </script>

这种方式相比较

方法起来更兼容 HTML 标准,它只依赖于可以运行 JavaScript 的客户端。

这两种方式在 HTTP header() 调用失败时都提供了可以接受的回退方式。理想化的处理方式应该是将跳转与其它方式结合,给出对用户友好的辅助信息并且提供一个可点的链接以供后续操作。

为什么 setcookie() 和 session_start() 都会被影响

setcookie() 和 session_start() 都需要发送一个 set-cookie: 的 HTTP 头信息。这种情况就和前面输出 header() 的情况类似,所以同样会出现由于过早地输出错误信息导致的错误。

(当然它们受影响也有可能是因为客户端禁止了 cookie 导致的,设置可能是代理的问题。很明显,session 也取决去剩余磁盘空间大小或者 php.ini 里的其它设置)

原文链接: http://stackoverflow.com/questions/8028957/how-to-fix-headers-already-sent-error-in-php

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
PHP:服務器端腳本語言的簡介PHP:服務器端腳本語言的簡介Apr 16, 2025 am 12:18 AM

PHP是一種服務器端腳本語言,用於動態網頁開發和服務器端應用程序。 1.PHP是一種解釋型語言,無需編譯,適合快速開發。 2.PHP代碼嵌入HTML中,易於網頁開發。 3.PHP處理服務器端邏輯,生成HTML輸出,支持用戶交互和數據處理。 4.PHP可與數據庫交互,處理表單提交,執行服務器端任務。

PHP和網絡:探索其長期影響PHP和網絡:探索其長期影響Apr 16, 2025 am 12:17 AM

PHP在過去幾十年中塑造了網絡,並將繼續在Web開發中扮演重要角色。 1)PHP起源於1994年,因其易用性和與MySQL的無縫集成成為開發者首選。 2)其核心功能包括生成動態內容和與數據庫的集成,使得網站能夠實時更新和個性化展示。 3)PHP的廣泛應用和生態系統推動了其長期影響,但也面臨版本更新和安全性挑戰。 4)近年來的性能改進,如PHP7的發布,使其能與現代語言競爭。 5)未來,PHP需應對容器化、微服務等新挑戰,但其靈活性和活躍社區使其具備適應能力。

為什麼要使用PHP?解釋的優點和好處為什麼要使用PHP?解釋的優點和好處Apr 16, 2025 am 12:16 AM

PHP的核心優勢包括易於學習、強大的web開發支持、豐富的庫和框架、高性能和可擴展性、跨平台兼容性以及成本效益高。 1)易於學習和使用,適合初學者;2)與web服務器集成好,支持多種數據庫;3)擁有如Laravel等強大框架;4)通過優化可實現高性能;5)支持多種操作系統;6)開源,降低開發成本。

揭穿神話:PHP真的是一種死語嗎?揭穿神話:PHP真的是一種死語嗎?Apr 16, 2025 am 12:15 AM

PHP沒有死。 1)PHP社區積極解決性能和安全問題,PHP7.x提升了性能。 2)PHP適合現代Web開發,廣泛用於大型網站。 3)PHP易學且服務器表現出色,但類型系統不如靜態語言嚴格。 4)PHP在內容管理和電商領域仍重要,生態系統不斷進化。 5)通過OPcache和APC等優化性能,使用OOP和設計模式提升代碼質量。

PHP與Python辯論:哪個更好?PHP與Python辯論:哪個更好?Apr 16, 2025 am 12:03 AM

PHP和Python各有優劣,選擇取決於項目需求。 1)PHP適合Web開發,易學,社區資源豐富,但語法不夠現代,性能和安全性需注意。 2)Python適用於數據科學和機器學習,語法簡潔,易學,但執行速度和內存管理有瓶頸。

PHP的目的:構建動態網站PHP的目的:構建動態網站Apr 15, 2025 am 12:18 AM

PHP用於構建動態網站,其核心功能包括:1.生成動態內容,通過與數據庫對接實時生成網頁;2.處理用戶交互和表單提交,驗證輸入並響應操作;3.管理會話和用戶認證,提供個性化體驗;4.優化性能和遵循最佳實踐,提升網站效率和安全性。

PHP:處理數據庫和服務器端邏輯PHP:處理數據庫和服務器端邏輯Apr 15, 2025 am 12:15 AM

PHP在數據庫操作和服務器端邏輯處理中使用MySQLi和PDO擴展進行數據庫交互,並通過會話管理等功能處理服務器端邏輯。 1)使用MySQLi或PDO連接數據庫,執行SQL查詢。 2)通過會話管理等功能處理HTTP請求和用戶狀態。 3)使用事務確保數據庫操作的原子性。 4)防止SQL注入,使用異常處理和關閉連接來調試。 5)通過索引和緩存優化性能,編寫可讀性高的代碼並進行錯誤處理。

您如何防止PHP中的SQL注入? (準備的陳述,PDO)您如何防止PHP中的SQL注入? (準備的陳述,PDO)Apr 15, 2025 am 12:15 AM

在PHP中使用預處理語句和PDO可以有效防範SQL注入攻擊。 1)使用PDO連接數據庫並設置錯誤模式。 2)通過prepare方法創建預處理語句,使用佔位符和execute方法傳遞數據。 3)處理查詢結果並確保代碼的安全性和性能。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器