setcookie

(PHP 4, PHP 5, PHP 7, PHP 8)

setcookie發(fā)送 Cookie

說(shuō)明

setcookie(
    string $name,
    string $value = "",
    int $expires = 0,
    string $path = "",
    string $domain = "",
    bool $secure = false,
    bool $httponly = false
): bool

PHP 7.3.0 起有效的簽名:

setcookie(string $name, string $value = "", array $options = []): bool

setcookie() 定義了 Cookie,會(huì)和剩下的 HTTP 頭一起發(fā)送給客戶(hù)端。 和其他 HTTP 頭一樣,必須在腳本產(chǎn)生任意輸出之前發(fā)送 Cookie(由于協(xié)議的限制)。 請(qǐng)?jiān)诋a(chǎn)生任何輸出之前(包括 <html><head> 或者空格)調(diào)用本函數(shù)。

一旦設(shè)置 Cookie 后,下次打開(kāi)頁(yè)面時(shí)可以使用 $_COOKIE 讀取。 Cookie 值同樣也存在于 $_REQUEST。

參數(shù)

? RFC 6265 提供了 setcookie() 每個(gè)參數(shù)的參考標(biāo)準(zhǔn)。

name

Cookie 名稱(chēng)。

value

Cookie 值。 這個(gè)值儲(chǔ)存于用戶(hù)的電腦里,請(qǐng)勿儲(chǔ)存敏感信息。 比如 name'cookiename', 可通過(guò) $_COOKIE['cookiename'] 獲取它的值。

expires

Cookie 的過(guò)期時(shí)間。 這是個(gè) Unix 時(shí)間戳,即 Unix 紀(jì)元以來(lái)(格林威治時(shí)間 1970 年 1 月 1 日 00:00:00)的秒數(shù)。 也就是說(shuō),基本可以用 time() 函數(shù)的結(jié)果加上希望過(guò)期的秒數(shù)。 或者也可以用 mktime()。 time()+60*60*24*30 就是設(shè)置 Cookie 30 天后過(guò)期。 如果設(shè)置成零,或者忽略參數(shù), Cookie 會(huì)在會(huì)話(huà)結(jié)束時(shí)過(guò)期(也就是關(guān)掉瀏覽器時(shí))。

注意:

你可能注意到了,expires 使用 Unix 時(shí)間戳而非 Wdy, DD-Mon-YYYY HH:MM:SS GMT 這樣的日期格式,是因?yàn)?PHP 內(nèi)部作了轉(zhuǎn)換。

path

Cookie 有效的服務(wù)器路徑。 設(shè)置成 '/' 時(shí),Cookie 對(duì)整個(gè)域名 domain 有效。 如果設(shè)置成 '/foo/', Cookie 僅僅對(duì) domain/foo/ 目錄及其子目錄有效(比如 /foo/bar/)。 默認(rèn)值是設(shè)置 Cookie 時(shí)的當(dāng)前目錄。

domain

Cookie 的有效域名/子域名。 設(shè)置成子域名(例如 'www.example.com'),會(huì)使 Cookie 對(duì)這個(gè)子域名和它的三級(jí)域名有效(例如 w2.www.example.com)。 要讓 Cookie 對(duì)整個(gè)域名有效(包括它的全部子域名),只要設(shè)置成域名就可以了(這個(gè)例子里是 'example.com')。

舊版瀏覽器仍然在使用廢棄的 ? RFC 2109, 需要一個(gè)前置的點(diǎn) . 來(lái)匹配所有子域名。

secure

設(shè)置這個(gè) Cookie 是否僅僅通過(guò)安全的 HTTPS 連接傳給客戶(hù)端。 設(shè)置成 true 時(shí),只有安全連接存在時(shí)才會(huì)設(shè)置 Cookie。 如果是在服務(wù)器端處理這個(gè)需求,程序員需要僅僅在安全連接上發(fā)送此類(lèi) Cookie (通過(guò) $_SERVER["HTTPS"] 判斷)。

httponly

設(shè)置成 true,Cookie 僅可通過(guò) HTTP 協(xié)議訪(fǎng)問(wèn)。 這意思就是 Cookie 無(wú)法通過(guò)類(lèi)似 JavaScript 這樣的腳本語(yǔ)言訪(fǎng)問(wèn)。 要有效減少 XSS 攻擊時(shí)的身份竊取行為,可建議用此設(shè)置(雖然不是所有瀏覽器都支持),不過(guò)這個(gè)說(shuō)法經(jīng)常有爭(zhēng)議。 truefalse

options

An associative array which may have any of the keys expires, path, domain, secure, httponly and samesite. If any other key is present an error of level E_WARNING is generated. The values have the same meaning as described for the parameters with the same name. The value of the samesite element should be either None, Lax or Strict. If any of the allowed options are not given, their default values are the same as the default values of the explicit parameters. If the samesite element is omitted, no SameSite cookie attribute is set.

返回值

如果在調(diào)用本函數(shù)以前就產(chǎn)生了輸出,setcookie() 會(huì)調(diào)用失敗并返回 false。 如果 setcookie() 成功運(yùn)行,返回 true。當(dāng)然,它的意思并非用戶(hù)是否已接受 Cookie。

范例

發(fā)送 Cookie 的幾個(gè)例子:

示例 #1 setcookie() 發(fā)送例子

<?php
$value 
'something from somewhere';

setcookie("TestCookie"$value);
setcookie("TestCookie"$valuetime()+3600);  /* 1 小時(shí)過(guò)期  */
setcookie("TestCookie"$valuetime()+3600"/~rasmus/""example.com"1);
?>

注意:在發(fā)送 Cookie 時(shí),值的部分會(huì)被自動(dòng) urlencode 編碼。收到 Cookie 時(shí),會(huì)自動(dòng)解碼,并賦值到可變的 Cookie 名稱(chēng)上。 如果不想被編碼,可以使用 setrawcookie() 代替。 在腳本里查看我們的測(cè)試 Cookie 的內(nèi)容,使用下面的一個(gè)例子:

<?php
// 打印一個(gè)單獨(dú)的 Cookie
echo $_COOKIE["TestCookie"];

//  debug/test 查看所有 Cookie 的另一種方式
print_r($_COOKIE);
?>

示例 #2 setcookie() 刪除例子

要?jiǎng)h除一個(gè) Cookie,應(yīng)該設(shè)置過(guò)期時(shí)間為過(guò)去,以觸發(fā)瀏覽器的刪除機(jī)制。 下面的例子展示了如何刪除上個(gè)例子里的 Cookie:

<?php
// 設(shè)置過(guò)期時(shí)間為一個(gè)小時(shí)前
setcookie("TestCookie"""time() - 3600);
setcookie("TestCookie"""time() - 3600"/~rasmus/""example.com"1);
?>

示例 #3 setcookie() 和數(shù)組

通過(guò)帶 array 標(biāo)記的 Cookie 名稱(chēng),也可以把 Cookie 設(shè)置成數(shù)組。 如果有數(shù)組元素,可以把它放進(jìn) Cookie 里; 腳本接收到時(shí),Cookie 名稱(chēng)里的值會(huì)是一個(gè)數(shù)組:

<?php
// 設(shè)置 Cookie
setcookie("cookie[three]""cookiethree");
setcookie("cookie[two]""cookietwo");
setcookie("cookie[one]""cookieone");

// 網(wǎng)頁(yè)刷新后,打印出以下內(nèi)容
if (isset($_COOKIE['cookie'])) {
    foreach (
$_COOKIE['cookie'] as $name => $value) {
        
$name htmlspecialchars($name);
        
$value htmlspecialchars($value);
        echo 
"$name : $value <br />\n";
    }
}
?>

以上例程會(huì)輸出:

three : cookiethree
two : cookietwo
one : cookieone

注意: Using separator characters such as [ and ] as part of the cookie name is not compliant to RFC 6265, section 4, but supposed to be supported by user agents according to RFC 6265, section 5.

更新日志

版本 說(shuō)明
7.3.0 An alternative signature supporting an options array has been added. This signature supports also setting of the SameSite cookie attribute.

注釋

注意:

要在調(diào)用本函數(shù)前輸出內(nèi)容,可以使用輸出緩沖:讓輸出的內(nèi)容在服務(wù)器里緩沖起來(lái), 直至真正發(fā)送給瀏覽器。 可在腳本里調(diào)用 ob_start()ob_end_flush(), 或設(shè)置 output_buffering php.ini 或服務(wù)器配置文件里的配置指令。

注意避坑:

  • 在頁(yè)面( Cookie 可見(jiàn)的頁(yè)面)下次刷新前,Cookie 不會(huì)生效。 測(cè)試 Cookie 是否已經(jīng)成功設(shè)置,需要在下次頁(yè)面加載時(shí)、Cookie 過(guò)期前檢測(cè)。 過(guò)期時(shí)間是通過(guò) expires 參數(shù)設(shè)置的。 直接調(diào)用 print_r($_COOKIE); 調(diào)試檢測(cè) Cookie 是個(gè)很好的方式。
  • 為同一個(gè)參數(shù)再次設(shè)置 Cookie 前,必須先把它刪掉。 如果參數(shù)的值是空 string 或 false,并且其他參數(shù)和上次調(diào)用 setcookie 仍舊一樣, 則指定的名稱(chēng)會(huì)被遠(yuǎn)程客戶(hù)端刪除。 內(nèi)部的實(shí)現(xiàn)是:將值設(shè)置成 'deleted',并且過(guò)期時(shí)間是一年前。
  • 因?yàn)樵O(shè)置值成 false 會(huì)導(dǎo)致 Cookie 被刪除,所以要避免使用布爾值。 代替方式:0false1true。
  • Cookie 名稱(chēng)可以設(shè)置成數(shù)組名稱(chēng),PHP 腳本里會(huì)是數(shù)組, 但用戶(hù)系統(tǒng)里儲(chǔ)存的是單獨(dú)分開(kāi)的 Cookie。 可以考慮使用 explode() 為一個(gè) Cookie 設(shè)置多個(gè)名稱(chēng)和值。 不建議將 serialize() 用于此處,因?yàn)樗鼤?huì)導(dǎo)致安全漏洞。

多次調(diào)用 setcookie() 會(huì)按調(diào)用順序執(zhí)行。

參見(jiàn)