PHP之COOKIE支持详解,cookie第一次PHP的COOKIE变量取不了值的原因说明

jackxiang 2010-1-12 21:24 | |
Cookie注意事项
1、SetCookie()之前不能有任何html输出,它认了第二,没有哪个元素敢认第一,就是空格,空白行都不行。
2、 SetCookie()后,你在当前页调用echo $_COOKIE["name"]不会有输出。必须刷新或到下一个页面才可以看到Cookie值。原因很简单。SetCookie()执行之后,往客户端发送一个cookie,你不刷新或浏览下一个页面,客户端怎么把cookie给你送回去呀?浏览器创建了一个Cookie后,对于每一个针对该网站的请求,都会在Header中带着这个Cookie;不过,对于其他网站的请求Cookie是绝对不会跟着发送的。而且浏览器会这样一直发送,直到 Cookie过期为止。

bool setcookie (string $name [, string $value [, int $expire [, string $path [, string $domain [, bool $secure]]]]] )
其中中括号内可以省略

$name 参数为Cookie变量名
$value 参数为COOkie值
$expire Cookie的失效时间 ,$expire是标准的UNIX时间标记,可以用time()函数或者mktime()函数获取,单位为秒,如:time()+3600*24*30表示Cookie的有效期为一个月,如果不进行设置默认为会话期间,即关闭浏览器时Cookie失效!
$path Cookie在服务器的有效路径
$domain Cookie有效域名
$secure 指明Cookie是否仅通过安全的HTTPS值为0或1,如果为1,则cookie只能在HTTPS连接有效;如果值为默认值0,则在HTTP和HTTPS连接上均有效





setcookie

(PHP 3, PHP 4, PHP 5)
setcookie -- 发送一个 cookie 信息
说明
bool setcookie ( string name [, string value [, int expire [, string path [, string domain [, bool secure]]]]] )

setcookie() 定义一个和其余的 HTTP 标头一起发送的 cookie。和其它标头一样,cookie 必须在脚本的任何其它输出之前发送(这是协议限制)。这需要将本函数的调用放到任何输出之前,包括 <html> 和 <head> 标签以及任何空格。如果在调用 setcookie() 之前有任何输出,本函数将失败并返回 FALSE。如果 setcookie() 函数成功运行,将返回 TRUE。这并不说明用户是否接受了 cookie。

     注: 自 PHP 4 起,可以用输出缓存来在调用本函数前输出内容,代价是把所有向浏览器的输出都缓存在服务器,直到下命令发送它们。可以在代码中使用 ob_start() 及 ob_end_flush() 来实现这样的功能,或者通过修改 php.ini 中的 output_buffering 配置选项来实现,也可以通过修改服务器配置文件来实现。

除了 name 外,其它所有参数都是可选的。可以用空字符串("")替换某参数以跳过该参数。因为参数 expire 是整型,不能用空字符串掉过,可以用零(0)来代替 。下面的表格对 setcookie() 的每一个参数都进行了解释。可以对照 Netscape cookie 规范以了解 setcookie() 的每一个参数的细节以及通过阅读 RFC 2965 了解 HTTP cookie 的工作方式。

表格 1. setcookie() 参数详解
参数 说明 举例
name Cookie 的名字。   使用 $_COOKIE['cookiename'] 调用名为 cookiename 的 cookie。
value Cookie 的值。此值保存在客户端,不要用来保存敏感数据。   假定 name 是 'cookiename',可以通过 $_COOKIE['cookiename'] 取得其值。
expire Cookie 过期的时间。这是个 Unix 时间戳,即从 Unix 纪元开始的秒数。换而言之,通常用 time() 函数再加上秒数来设定 cookie 的失效期。或者用 mktime()来实现。   time()+60*60*24*30 将设定 cookie 30 天后失效。如果未设定,cookie 将会在会话结束后(一般是浏览器关闭)失效。
path Cookie 在服务器端的有效路径。   如果该参数设为 '/' 的话,cookie 就在整个 domain 内有效,如果设为 '/foo/',cookie 就只在 domain 下的 /foo/ 目录及其子目录内有效,例如 /foo/bar/。默认值为设定 cookie 的当前目录。
domain 该 cookie 有效的域名。   要使 cookie 能在如 example.com 域名下的所有子域都有效的话,该参数应该设为 '.example.com'。虽然 . 并不必须的,但加上它会兼容更多的浏览器。如果该参数设为 www.example.com 的话,就只在 www 子域内有效。细节见 Cookie 规范中的 tail matching。
secure 指明 cookie 是否仅通过安全的 HTTPS 连接传送。当设成 TRUE 时,cookie 仅在安全的连接中被设置。默认值为 FALSE。   0 或 1

当 cookie 被设置后,便可以在其它页面通过 $_COOKIE 或 $HTTP_COOKIE_VARS 数组取得其值。需要注意的是,autoglobals 的 $_COOKIE 形式适用于 PHP 4.1.0 或更高版本。而 $HTTP_COOKIE_VARS 则从 PHP 3 起就可以使用。Cookie 的值也会被保存到 $_REQUEST 数组中。

     注: 如果 PHP 的选项 register_globals 被设为 on 的话,cookie 的值仍然会被斌到变量内。在下面的例子中,$TestCookie 会被注册,但是仍然推荐使用 $_COOKIE 数组。

常见缺陷:

     *

       Cookies 不会在设置它的本页生效,要测试一个 cookie 是否被成功的设定,可以在其到期之前通过另外一个页面来访问其值。过期时间是通过参数 expire 来设置的。可以简单地使用 print_r($_COOKIE); 来调试现有的 cookies。
     *

       Cookie 必须用和设定时的同样的参数才能删除。如果其值一个空字符串,或者是 FALSE,并且其它的参数都和前一次调用 setcookie 时相同,那么所指定名称的 cookie 将会在远程客户端被删除。
     *

       由于把 cookie 的值设为 FALSE 会使客户端尝试删除这个 cookie,所以要在 cookie 上保存 TRUE 或 FALSE 时不应该直接使用 boolean 值,而应该用 0 来表示 FALSE,用 1 来表示 TRUE
     *

       可以把 cookie 的名称设置成一个数组,但是数组 cookie 中的每个元素的值将会被单独保存在用户的系统中。考虑使用 explode() 函数用多个名称和值设定一个 cookie。不推荐将 serialize() 用于此目的,因为它可能会导致一个安全漏洞。

在 PHP 3 中,在同一个 PHP 脚本中多次使用 setcookie() 来设置 cookie,将会按照倒序的方式来分别执行,如果想要在插入另外一个 cookie 之前删除一个 cookie,要把插入放到删除之前。自 PHP 4 起,多次调用 setcookie() 则是按照顺序来执行的。

下面一些例子说明了如何发送 cookie:

例子 1. setcookie() 发送例子

$value = 'something from somewhere';

setcookie("TestCookie", $value);
setcookie("TestCookie", $value,time()+3600);   /* expire in 1 hour */
setcookie("TestCookie", $value,time()+3600, "/~rasmus/", ".utoronto.ca", 1);


注意 cookie 中值的部分在发送的时候会被自动用 urlencode 编码并在接收到的时候被自动解码并把值赋给与自己同名的 cookie 变量。如果不想这样并且在使用 PHP 5 的话,可以用 setrawcookie() 来代替。下面这个简单的例子可以得到刚才所设定的 cookie 的值:

<?php
// 输出单独的 cookie
echo $_COOKIE["TestCookie"];
echo $HTTP_COOKIE_VARS["TestCookie"];

// 另一个调试的方法就是输出所有的 cookie
print_r($_COOKIE);
?>

要删除 cookie 需要确保它的失效期是在过去,才能触发浏览器的删除机制。下面的例子说明了如何删除刚才设置的 cookie:

例子 2. setcookie() 删除例子
// 将过期时间设为一小时前
setcookie("TestCookie", "", time() - 3600);
setcookie("TestCookie", "", time() - 3600, "/~rasmus/", ".utoronto.ca", 1);

也可以通过在 cookie 名称中使用数组符号来设定数组 cookie,可以设定多个 cookie 作为数组单元,在脚本提取 cookie 时所有的值都放在一个数组种:

例子 3. setcookie() 中使用数组的例子

<?php
// 设定 cookie
setcookie("cookie[three]", "cookiethree");
setcookie("cookie[two]", "cookietwo");
setcookie("cookie[one]", "cookieone");

// 刷新页面后,显示出来
if (isset($_COOKIE['cookie'])) {
    foreach ($_COOKIE['cookie'] as $name => $value) {
        echo "$name : $value <br />\n";
    }
}
?>

上例将输出:

three : cookiethree
two : cookietwo
one : cookieone


     注: 下面的一些 RFC 也具参考价值:RFC 2109 和 RFC 2695。

     注意 expire 参数的接受的是 Unix 时间戳,而不是日期格式 Wdy, DD-Mon-YYYY HH:MM:SS GMT,这是因为 PHP 在内部进行了转换。

     expire 是与客户端的时间相比较,和服务器时间可能不同。

     注: 向 Microsoft Internet Explorer 4 Service Pack 1 不能正确处理设定了 path 的 cookie。



1、设置Cookie

PHP用SetCookie函数来设置Cookie。必须注意的一点是:Cookie是HTTP协议头的一部分,用于浏览器和服务器之间传递信息,所以必须在任何属于HTML文件本身的内容输出之前调用Cookie函数。
SetCookie函数定义了一个Cookie,并且把它附加在HTTP头的后面,SetCookie函数的原型如下:
int SetCookie(string name, string value, int expire, string path, string domain, int secure);
除了name之外所有的参数都是可选的。value,path,domain三个参数可以用空字符串代换,表示没有设置;expire 和 secure两个参数是数值型的,可以用0表示。expire参数是一个标准的Unix时间标记,可以用time()或mktime()函数取得,以秒为单位。 secure参数表示这个Cookie是否通过加密的HTTPS协议在网络上传输。
当前设置的Cookie不是立即生效的,而是要等到下一个页面时才能看到.这是由于在设置的这个页面里Cookie由服务器传递给客户浏览器,在下一个页面浏览器才能把Cookie从客户的机器里取出传回服务器的原因。
在同一个页面设置Cookie,实际是从后往前,所以如果要在插入一个新的Cookie之前删掉一个,你必须先写插入的语句,再写删除的语句,否则可能会出现不希望的结果。
来看几个例子:
简单的:
SetCookie("MyCookie", "Value of MyCookie");
带失效时间的:
SetCookie("WithExpire", "Expire in 1 hour", time()+3600);//3600秒=1小时
什么都有的:
SetCookie("FullCookie", "Full cookie value", time()+3600, "/forum", ".phpuser.com", 1);

这里还有一点要说明的,比如你的站点有几个不同的目录,那么如果只用不带路径的Cookie的话,在一个目录下的页面里设的Cookie在另一个目录的页面里是看不到的,也就是说,Cookie是面向路径的。实际上,即使没有指定路径,WEB服务器会自动传递当前的路径给浏览器的,指定路径会强制服务器使用设置的路径。解决这个问题的办法是在调用SetCookie时加上路径和域名,域名的格式可以是“www.phpuser.com”,也可是 “.phpuser.com”。
SetCookie函数里表示value的部分,在传递时会自动被encode,也就是说,如果 value的值是“test value”在传递时就变成了“test%20value”,跟URL的方法一样。当然,对于程序来说这是透明的,因为在 PHP接收Cookie的值时会自动将其decode。
如果要设置同名的多个Cookie,要用数组,方法是:
SetCookie("CookieArray[]", "Value 1");
SetCookie("CookieArray[]", "Value 2");

SetCookie("CookieArray[0]", "Value 1");
SetCookie("CookieArray[1]", "Value 2");

2、接收和处理Cookie

PHP对Cookie的接收和处理的支持非常好,是完全自动的,跟FORM变量的原则一样,特别简单。
比如设置一个名为MyCookier的Cookie,PHP会自动从WEB服务器接收的HTTP头里把它分析出来,并形成一个与普通变量一样的变量,名为 $myCookie,这个变量的值就是Cookie的值。数组同样适用。另外一个办法是引用PHP的全局变量$HTTP_COOKIE_VARS数组。
分别举例如下:(假设这些都在以前的页面里设置过了,并且仍然有效)
echo $MyCookie;
echo $CookieArray[0];
echo count($CookieArray);
echo $HTTP_COOKIE_VARS["MyCookie"];
就这么简单。

3、删除Cookie

要删除一个已经存在的Cookie,有两个办法:
一是调用只带有name参数的SetCookie,那么名为这个name的Cookie将被从关系户机上删掉;另一个办法是设置Cookie的失效时间为 time()或time()-1,那么这个Cookie在这个页面的浏览完之后就被删除了(其实是失效了)。
要注意的是,当一个Cookie被删除时,它的值在当前页在仍然有效的。

4、使用Cookie的限制

首先是必须在HTML文件的内容输出之前设置;
其次不同的浏览器对Cookie的处理不一致辞,且有时会出现错误的结果。比如:MS IE+SERVICE PACK 1不能正确处理带域名和路径的 Cookie,Netscape Communicator 4.05和MS IE 3.0不能正确处理不带路径和时间的Cookie。至于 MS IE 5 好象不能处理带域名、路径和时间的Cookie。这是我在设计本站的页面时发现的。
第三个限制是在客户端的。一个浏览器能创建的Cookie数量最多为30个,并且每个不能超过4KB,每个WEB站点能设置的Cookie总数不能超过20个。

关于Cookie的话题,就说到这儿了。  
     Netscape Communicator 4.05 及 Microsoft Internet Explorer 3.x 不能正确处理没有设定 path 和 time 的 cookie。

作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:https://jackxiang.com/post/2547/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!


最后编辑: jackxiang 编辑于2011-2-18 20:03
评论列表
2010-1-13 14:42 | 虫下
dog
2010-1-13 14:42 | 虫下
今天好冷啊。。
分页: 1/1 第一页 1 最后页
发表评论

昵称

网址

电邮

打开HTML 打开UBB 打开表情 隐藏 记住我 [登入] [注册]