相信大多数人在写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就是基于这种原理的。