相信大多數人在寫PHP代碼的時候,都遇到過相似"Warning: Cannot send session cookie – headers already sent…「或者」Cannot add/modify header information – headers already sent…"這樣的Warning提示.下面咱們就來看看發生這個Warning的緣由及解決方案。php
函數 header(),setcookie() 和 session 函數須要在輸出流中增長頭信息。可是頭信息只能在其它任何輸出內容以前發送。在使用這些函數前不能有任何(如 HTML)的輸出。函數 headers_sent() 可以檢查您的腳本是否已經發送了頭信息。請參閱「輸出控制函數」。瀏覽器
headers_sent — Checks if or where headers have been sent.緩存
意思是:不要在使用上面的函數前有任何文字,空行,回車,空格等。但。。。問題是,這答案並不使人滿意。由於每每程序在其餘PHP環境下運行卻正常。cookie
首先:這錯誤是怎麼產生的呢?讓咱們來看看PHP是如何處理HTTP header輸出和主體輸出的。session
PHP腳本開始執行時,它能夠同時發送header(標題)信息和主體信息。 Header信息(來自 header() 或 SetCookie() 函數)並不會當即發送,相反,它被保存到一個列表中。 這樣就能夠容許你修改標題信息,包括缺省的標題(例如 Content-Type 標題)。可是,一旦腳本發送了任何非標題的輸出(例如,使用 HTML, print()或echo 調用),那麼PHP就必須先發送完全部的Header,而後終止 HTTP header。然後繼續發送主體數據。從這時開始,任何添加或修改Header信息的試圖都是不容許的,並會發送上述的錯誤消息之一。編輯器
下面咱們來看看解決方案:ide
1. 把錯誤警告全不顯示, 治標不治本的方法函數
error_reporting(E_ERROR | E_PARSE); 這裏不要顯示E_WARNING便可編碼
2. 編輯php.iniorm
打開php.ini文件, 找到output_buffering = 改成on或者任何數字。
3. 若是沒有權限編輯php.ini,如使用虛擬主機的
在你的空間根目錄下創建一個。htaccess文件,內容以下:
AllowOverride AllPHP_FLAG output_buffering On
若是仍是不行,那麼,再用下面的方法:
在PHP文件的最開始加入:ini_set(」output_buffering」, 「1″);
讓這個頁面打開PHP的輸出緩存。
4. 在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到瀏覽器,而後再發送輸出緩衝中的內容。
5. 若是以上方法都不能等到滿意的解決辦法,請用以下辦法:
用notepad++等編輯器將該文件轉爲UTF-8 without BOM編碼的文件,再試試.
形成的緣由主要由如下兩點:
一,在Header()函數之間輸出了其餘內容(通常由瀏覽器隱藏發送),致使了後來的Header不能再次發送新的頁面類型。這能夠經過開啓Output_Buffering來解決,方法2,3,4就是這樣。
二,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就能夠了,方法5就是基於這種原理的。