setcookie

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

setcookie發(fā)送 Cookie

說明

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,會和剩下的 HTTP 頭一起發(fā)送給客戶端。 和其他 HTTP 頭一樣,必須在腳本產(chǎn)生任意輸出之前發(fā)送 Cookie(由于協(xié)議的限制)。 請在產(chǎn)生任何輸出之前(包括 <html><head> 或者空格)調(diào)用本函數(shù)。

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

參數(shù)

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

name

Cookie 名稱。

value

Cookie 值。 這個值儲存于用戶的電腦里,請勿儲存敏感信息。 比如 name'cookiename', 可通過 $_COOKIE['cookiename'] 獲取它的值。

expires

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

注意:

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

path

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

domain

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

舊版瀏覽器仍然在使用廢棄的 ? RFC 2109, 需要一個前置的點 . 來匹配所有子域名。

secure

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

httponly

設(shè)置成 true,Cookie 僅可通過 HTTP 協(xié)議訪問。 這意思就是 Cookie 無法通過類似 JavaScript 這樣的腳本語言訪問。 要有效減少 XSS 攻擊時的身份竊取行為,可建議用此設(shè)置(雖然不是所有瀏覽器都支持),不過這個說法經(jī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() 會調(diào)用失敗并返回 false。 如果 setcookie() 成功運行,返回 true。當(dāng)然,它的意思并非用戶是否已接受 Cookie。

范例

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

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

<?php
$value 
'something from somewhere';

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

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

<?php
// 打印一個單獨的 Cookie
echo $_COOKIE["TestCookie"];

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

示例 #2 setcookie() 刪除例子

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

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

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

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

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

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

以上例程會輸出:

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.

更新日志

版本 說明
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ù)器里緩沖起來, 直至真正發(fā)送給瀏覽器。 可在腳本里調(diào)用 ob_start()ob_end_flush(), 或設(shè)置 output_buffering php.ini 或服務(wù)器配置文件里的配置指令。

注意避坑:

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

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

參見