如果在執行php程式時看到這條警告:"Warning: Cannot modify header information - headers already sent by ...."
Few notes based on the following user posts:
有以下幾種解決方案:
1. Blank lines (空白行):
Make sure no blank line after <?php ... ?> of the calling php scrīpt.
檢查有<?php ... ?> 後面沒有空白行,特別是include或者require的檔案。不少問題是這些空白行導致的。
2. Use exit statement (用exit來解決):
Use exit after header statement seems to help some people
在header後加上exit();
header ("Location: xxx");
exit();
3. PHP has this annoying problem, if your HTML goes before any PHP code or any header modification before redirecting to certain page, it ll said "Warning: Cannot modify header information - headers already sent by ...." Basically anytime you output to browser, the header is set and cannot be modified. So two ways to get around the problem:
3a. Use Javascrīpt (用Javascrīpt來解決):
<? echo "<scrīpt> self.location( file.php );</scrīpt>"; ?>
Since it s a scrīpt, it won t modify the header until execution of Javascrīpt.
可以用Javascrīpt來代替header。另外需要注意,採用這種方法需要瀏覽器支援Javascrīpt.
3b. Use output buffering (用輸出緩衝來解決):
<?php ob_start(); ?>
... HTML codes ...
<?php
... PHP codes ...
header ("Location: ....");
ob_end_flush();
?>
This will save the output buffer on server and not output to browser yet, which means you can modify the header all you want until the ob_end_flush() statement. This method is cleaner than the Javascrīpt since Javascrīpt method assumes the browser has Javascrīpt turn on. However, there are overhead to store output buffer on server before output, but with modern hardware I would imagine it won t be that big of deal. Javascrīpt solution would be better if you know for sure your user has Javascrīpt turn on on their browser.
就像上面的代碼那樣,這種方法在產生頁面的時候緩衝,這樣就允許在輸出head之後再輸出header了。本站的許願板就是採用這種方法解決的header問題。
4.set output_buffering = On in php.ini (開啟php.ini中的output_buffering )
set output_buffering = On will enable output buffering for all files. But this method may slow down your php output. The performance of this method depends on which Web server you re working with, and what kind of scrīpts you re using.
這種方法和3b的方法理論上是一樣的。但是這種方法開啟了所有php程式的輸出緩衝,這樣做可能影響php執行效率,這取決於伺服器的效能和代碼的複雜度。
第二種:
如何徹底杜絕warning: Cannot add header information - headers already sent in…… 這種令人莫明其妙的的錯誤。 只要你寫過PHP代碼,相信都遇上過這個大多時候都令人莫明其妙的warning吧..今天我們就來搞定它…………… 看了PHP手冊,回答如下:訊息“Warning: Cannot send session cookie - headers already sent…”或者“Cannot add/modify header information - headers already sent…”。 函數 header(),setcookie() 和 session 函數需要在輸出資料流中增加頭資訊。但是頭資訊只能在其它任何輸出內容之前發送。在使用這些函數前不能有任何(如 HTML)的輸出。函數 headers_sent() 能夠檢查您的指令碼是否已經發送了頭資訊。請參閱“輸出控制函數”。 意思是:不要在使用上面的函數前有任何文字,空行,斷行符號,空格等。但。。。問題是,這答案並不令人滿意。因為往往程式在其他PHP環境下運行卻正常。 首先:這錯誤是怎麼產生的呢?讓我們來看看PHP是如何處理HTTP header輸出和主體輸
文討論的是如何徹底杜絕warning: Cannot add header information - headers already sent in…… 這種令人莫明其妙的的錯誤。
只要你寫過PHP代碼,相信都遇上過這個大多時候都令人莫明其妙的warning吧..今天我們就來搞定它……………
看了PHP手冊,回答如下:
訊息“Warning: Cannot send session cookie - headers already sent…”或者“Cannot add/modify header information - headers already sent…”。
函數 header(),setcookie() 和 session 函數需要在輸出資料流中增加頭資訊。但是頭資訊只能在其它任何輸出內容之前發送。在使用這些函數前不能有任何(如 HTML)的輸出。函數 headers_sent() 能夠檢查您的指令碼是否已經發送了頭資訊。請參閱“輸出控制函數”。
意思是:不要在使用上面的函數前有任何文字,空行,斷行符號,空格等。但。。。問題是,這答案並不令人滿意。因為往往程式在其他PHP環境下運行卻正常。
首先:這錯誤是怎麼產生的呢?讓我們來看看PHP是如何處理HTTP header輸出和主體輸出的。
PHP指令碼開始執行時,它可以同時發送header(標題)資訊和主體資訊。 Header資訊(來自 header() 或 SetCookie() 函數)並不會立即發送,相反,它被儲存到一個列表中。 這樣就可以允許你修改標題資訊,包括預設的標題(例如 Content-Type 標題)。但是,一旦指令碼發送了任何非標題的輸出(例如,使用 HTML 或 print() 調用),那麼PHP就必須先發送完所有的Header,然後終止 HTTP header。而後繼續發送主體資料。從這時開始,任何添加或修改Header資訊的試圖都是不允許的,並會發送上述的錯誤訊息之一。
好!那我們來解決它:笨方法:把錯誤警告全不顯示! 掩耳盜鈴之計
error_reporting(E_ERROR | E_PARSE); 這裡不要顯示E_WARNING即可
解決方案:
1)適用於有許可權編輯PHP。INI的人
開啟php。ini檔案(你應試比我清楚你的php。ini在哪裡),找到
output_buffering =改為on或者任何數字。如果是IIS6,請一定改為ON,不然你的PHP效率會奇慢。
2)使用虛擬機器主機,不能編輯PHP。INI,怎麼辦?
簡單:
在你的空間根目錄下建立一個。htaccess檔案,內容如下:
AllowOverride All
PHP_FLAG output_buffering On
不幸的情況是:還是不行?全部網頁都不能顯示啦?
那麼,再用下面的方法:
在PHP檔案的最開始加入:ini_set("output_buffering", "1");
讓這個頁面開啟PHP的輸出緩衝。
3)在PHP檔案裡解決
ob_start()
啟用output buffering機制。 Output buffering支援多層次 — 例如,可以多次調用 ob_start() 函數。
ob_end_flush()
發送output buffer(輸出緩衝)並禁用output buffering機制。
ob_end_clean()
清除output buffer但不發送,並禁用output buffering。
ob_get_contents()
將當前的output buffer返回成一個字串。允許你處理指令碼發出的任何輸出。
原理:
output_buffering被啟用時,在指令碼發送輸出時,PHP並不發送HTTP header。相反,它將此輸出通過管道(pipe)輸入到動態增加的緩衝中(只能在PHP 4。0中使用,它具有中央化的輸出機制)。你仍然可以修改/添加header,或者設定cookie,因為header實際上並沒有發送。當全部指令碼終止時,PHP將自動發送HTTP header到瀏覽器,然後再發送輸出緩衝中的內容。
4)絕殺技巧
如果以上方法都不能等到滿意的解決辦法,請用如下辦法:
先用記事本開啟出現問題的網頁,另存新檔ANSI編碼的同名檔案。
再用EditPlus將該檔案另存新檔UTF-8編碼的檔案。
再試試,應該可以顯示了。
造成的原因主要由以下兩點:
一:在Header()函數之間輸出了其他內容(一般由瀏覽器隱藏發送),導致了後來的Header不能再次發送新的頁面類型。這可以通過開啟Output_Buffering來解決,方法2)與3)就是這樣。
二:PHP檔案採用UTF-8編碼,由於編碼不相容(特別是通過其他編碼轉換過來的),產生了BOM《在UCS 編碼中有一個叫做"ZERO WIDTH NO-BREAK SPACE"的字元,它的編碼是FEFF。而FFFE在UCS中是不存在的字元,所以不應該出現在實際傳輸中。UCS規範建議我們在傳輸位元組流前,先傳輸 字元"ZERO WIDTH NO-BREAK SPACE"。這樣如果接收者收到FEFF,就表明這個位元組流是Big-Endian的;如果收到FFFE,就表明這個位元組流是Little- Endian的。因此字元"ZERO WIDTH NO-BREAK SPACE"又被稱作BOM。
UTF-8不需要BOM來表明位元組順序,但可以用BOM來表明編碼方式。字元"ZERO WIDTH NO-BREAK SPACE"的UTF-8編碼是EF BB BF。所以如果接收者收到以EF BB BF開頭的位元組流,就知道這是UTF-8編碼了。
Windows就是使用BOM來標記文字檔的編碼方式的。》導致了的標頭檔不能正確識別,這時只要去除UTF-8檔案中的BOM就可以了,方法4)就是基於這種原理的。
出的。 PHP指令碼開始執行時,它可以同時發送header(標題)資訊和主體資訊。 Header資訊(來自 header() 或 SetCookie() 函數)並不會立即發送,相反,它被儲存到一個列表中。 這樣就可以允許你修改標題資訊,包括預設的標題(例如 Content-Type 標題)。但是,一旦指令碼發送了任何非標題的輸出(例如,使用 HTML 或 print() 調用),那麼PHP就必須先發送完所有的Header,然後終止 HTTP header。而後繼續發送主體資料。從這時開始,任何添加或修改Header資訊的試圖都是不允許的,並會發送上述的錯誤訊息之一。 好!那我們來解決它:笨方法:把錯誤警告全不顯示! 掩耳盜鈴之計 error_reporting(E_ERROR | E_PARSE); 這裡不要顯示E_WARNING即可 解決方案: 1)適用於有許可權編輯PHP。INI的人開啟php。ini檔案(你應試比我清楚你的php。ini在哪裡),找到 output_buffering =改為on或者任何數字。如果是IIS6,請一定改為ON,不然你的PHP效率會奇慢。 2)使用虛擬機器主機,不能編輯PHP。INI,怎麼辦? 簡單:在你的空間根目錄下建立一個。htaccess檔案,內容如下: AllowOverride All PHP_FLAG output_buffering On 不幸的情況是:還是不行?全部網頁都不能顯示啦? 那麼,再用下面的方法: 在PHP檔案的最開始加入:ini_set("output_buffering", "1"); 讓這個頁面開啟PHP的輸出緩衝。 3)在PHP檔案裡解決 ob_start() 啟用output buffering機制。 Output buffering支援多層次 — 例如,可以多次調用 ob_start() 函數。 ob_end_flush() 發送output buffer(輸出緩衝)並禁用output buffering機制。 ob_end_clean() 清除output buffer但不發送,並禁用output buffering。 ob_get_contents() 將當前的output buffer返回成一個字串。允許你處理指令碼發出的任何輸出。 原理: output_buffering被啟用時,在指令碼發送輸出時,PHP並不發送HTTP header。相反,它將此輸出通過管道(pipe)輸入到動態增加的緩衝中(只能在PHP 4。0中使用,它具有中央化的輸出機制)。你仍然可以修改/添加header,或者設定cookie,因為header實際上並沒有發送。當全部指令碼終止時,PHP將自動發送HTTP header到瀏覽器,然後再發送輸出緩衝中的內容。 4)絕殺技巧 如果以上方法都不能等到滿意的解決辦法,請用如下辦法: 先用記事本開啟出現問題的網頁,另存新檔ANSI編碼的同名檔案。 再用EditPlus將該檔案另存新檔UTF-8編碼的檔案。 再試試,應該可以顯示了。 造成的原因主要由以下兩點: 一:在Header()函數之間輸出了其他內容(一般由瀏覽器隱藏發送),導致了後來的Header不能再次發送新的頁面類型。這可以通過開啟Output_Buffering來解決,方法2)與3)就是這樣。 二:PHP檔案採用UTF-8編碼,由於編碼不相容(特別是通過其他編碼轉換過來的),產生了BOM《在UCS 編碼中有一個叫做"ZERO WIDTH NO-BREAK SPACE"的字元,它的編碼是FEFF。而FFFE在UCS中是不存在的字元,所以不應該出現在實際傳輸中。UCS規範建議我們在傳輸位元組流前,先傳輸 字元"ZERO WIDTH NO-BREAK SPACE"。這樣如果接收者收到FEFF,就表明這個位元組流是Big-Endian的;如果收到FFFE,就表明這個位元組流是Little- Endian的。因此字元"ZERO WIDTH NO-BREAK SPACE"又被稱作BOM。 UTF-8不需要BOM來表明位元組順序,但可以用BOM來表明編碼方式。字元"ZERO WIDTH NO-BREAK SPACE"的UTF-8編碼是EF BB BF。所以如果接收者收到以EF BB BF開頭的位元組流,就知道這是UTF-8編碼了。 Windows就是使用BOM來標記文字檔的編碼方式的。》導致了的標頭檔不能正確識別,這時只要去除UTF-8檔案中的BOM就可以了,方法4)就是基於這種原理的。