setcookie
(PHP 4, PHP 5)
setcookie — Посылает cookie
Описание
$name
[, string $value
[, int $expire
= 0
[, string $path
[, string $domain
[, bool $secure
= false
[, bool $httponly
= false
]]]]]] )setcookie() задает cookie, которое будет передано клиенту вместе с другими HTTP заголовками. Как и любой другой заголовок, cookie должны передаваться до того как будут выведены какие-либо другие данные скрипта (это ограничение протокола). Это значит, что в скрипте вызовы этой функции должны располагаться прежде остального вывода, включая вывод тэгов <html> и <head>, а также пустые строки и пробелы.
После передачи клиенту cookie станут доступны через массивы $_COOKIE и $HTTP_COOKIE_VARS при следующей закгрузке страницы. Следует иметь в виду, что суперглобальные переменные, такие как $_COOKIE, стали доступны только в PHP 4.1.0. Значения cookie также есть в $_REQUEST.
Список параметров
Все аргументы, за исключением name
, являются
необязательными. Если нужно пропустить какой-либо аргумент, можно вместо
него поставить пустую строку (""). Это не
относится к аргументу expire
. Так как он принимает
значение типа integer, для его замены пустая строка не подходит. Используйте
вместо нее ноль (0).
» RFC 6265 дает конкретные указания, как нужно интерпретировать каждый из параметров setcookie().
-
name
-
Наименование cookie.
-
value
-
Значение cookie. Это значение будет сохранено на клиентском компьютере; не записывайте в cookie секретные данные. Значение присвоенное cookie c именем
name
, допустим, 'cookiename', будет доступно через $_COOKIE['cookiename']. -
expire
-
Время, когда срок действия cookie истекает. Это метка времени Unix, то есть это количество секунд с начала эпохи. Другими словами, желательно задавать это время с помощью функции time(), прибавляя время в секундах, через которое срок действия cookie должен истечь. Либо можно воспользоваться функцией mktime(). time()+60*60*24*30 установит срок действия cookie 30 дней. Если задать 0 или пропустить этот аргумент, срок действия cookie истечет с окончанием сессии (при закрытии броузера).
Замечание:
Можно заметить, что
expire
принимает в качестве значения метку времени Unix, а хранит его в формате Wdy, DD-Mon-YYYY HH:MM:SS GMT. PHP делает внутреннее преобразование автоматически. -
path
-
Путь к директории на сервере, из которой будут доступны cookie. Если задать '/', cookie будут доступны во всем домене
domain
. Если задать '/foo/', cookie будут доступны только из директории /foo/ и всех ее поддиректорий (например, /foo/bar/) доменаdomain
. По умолчанию значением является текущая директория, в которой cookie устанавливается. -
domain
-
Домен, которому доступны cookie. Задание домена 'www.example.com' сделает cookie доступными в поддомене www и поддоменах более высоких порядков. Cookie доступные низким уровням, таким как 'example.com', будут доступны во всех поддоменах высших уровней, с том числе 'www.example.com'. Старые броузеры, следующие устаревшим нормативам » RFC 2109, могут требовать . перед доменом, чтобы включались все поддомены.
-
secure
-
Указывает на то, что значение cookie должно передаваться от клиента по защищенному HTTPS соединению. Если задано
TRUE
, cookie от клиента будет передано на сервер, только если установлено защищенное соединение. При передаче cookie от сервера клиенту следить за тем, чтобы cookie этого типа передавались по защищенному каналу, должен программист веб-сервера (стоит обратить внимание на $_SERVER["HTTPS"]). -
httponly
-
Если задано
TRUE
, cookie будут доступны только через HTTP протокол. То есть cookie в этом случае не будут доступны скриптовым языкам, вроде JavaScript. Эта возможность была предложена в качестве меры, эффективно снижающей количество краж личных данных посредством XSS атак (несмотря на то, что поддерживается не всеми броузерами). Стоит однако же отметить, что вокруг этой возможности часто возникают споры о ее эффективности и целесообразности. Аргумент добавлен в PHP 5.2.0. Может принимать значенияTRUE
илиFALSE
.
Возвращаемые значения
Если перед вызовом функции клиенту уже передавался какой-либо вывод (тэги,
пустые строки, пробелы, текст и т.п.),
setcookie() вызовет отказ и вернет FALSE
. Если
setcookie() успешно отработает, то вернет TRUE
.
Это, однако, не означает, что клиентское приложение (броузер) правильно приняло
и обработало cookie.
Примеры
Ниже представлено несколько примеров, как отправлять cookie:
Пример #1 Пример использования setcookie()
<?php
$value = 'что-то где-то';
setcookie("TestCookie", $value);
setcookie("TestCookie", $value, time()+3600); /* срок действия 1 час */
setcookie("TestCookie", $value, time()+3600, "/~rasmus/", "example.com", 1);
?>
Стоит отметить, что значение cookie перед отправкой клиенту подвергается URL-кодированию. При обратном получении значение cookie декодируется и помещается в переменную, с тем же именем, что и имя cookie. Если вы не хотите, чтобы значения кодировались, используйте функцию setrawcookie() (работает в PHP 5). Посмотреть содержимое наших тестовых cookie можно, запустив один из следующих примеров:
<?php
// Вывести одно конкретное значение cookie
echo $_COOKIE["TestCookie"];
echo $HTTP_COOKIE_VARS["TestCookie"];
// В целях тестирования и отладки может пригодиться вывод всех cookie
print_r($_COOKIE);
?>
Пример #2 Пример удаления cookie посредством setcookie()
Чтобы удалить cookie достаточно в качестве срока действия указать какое-либо время в прошлом. Это запустит механизм броузера, удаляющий истекшие cookie. В примерах ниже показано, как удалить cookie, заданные в предыдущих примерах:
<?php
// установка даты истечения срока действия на час назад
setcookie ("TestCookie", "", time() - 3600);
setcookie ("TestCookie", "", time() - 3600, "/~rasmus/", "example.com", 1);
?>
Пример #3 setcookie() и массивы
Имеется возможность помещать в cookie массивы. Для этого каждому cookie нужно дать имя в соответствии с правилами именования массивов. Такая возможность позволяет поместить столько значений, сколько имеется элементов в массиве. При обратном получении все эти значения будут помещены в массив с именем этого cookie:
<?php
// отправка cookie
setcookie("cookie[three]", "cookiethree");
setcookie("cookie[two]", "cookietwo");
setcookie("cookie[one]", "cookieone");
// после перезагрузки страницы, выведем cookie
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
Список изменений
Версия | Описание |
---|---|
5.2.0 |
Добавлен параметр httponly .
|
Примечания
Замечание:
Чтобы иметь возможность отправлять вывод скрипта до вызова этой функции, можно воспользоваться буферизацией. В этом случае весь вывод скрипта помещается в буфер на сервере и остается там, пока вы явно не отправите его броузеру. Управление буферизацией осуществляется функциями ob_start() и ob_end_flush() в скрипте, либо можно задать директиву output_buffering в файле php.ini или конфигурационных файлах сервера.
Замечание:
Если PHP директива register_globals включена (задано значение on), значения cookie помимо всего прочего будут помещаться в переменные. Для примеров выше будет существовать переменная $TestCookie. Тем не менее, рекомендуется использовать $_COOKIE.
Общие замечания:
-
Cookie станут видимыми только после перезагрузки страницы, для которой
они должны быть видны. Для проверки, правильно ли cookie установились,
проверьте их при следующей загрузке страницы до истечения срока их
действия. Срок действия cookie задается в параметре
expire
. Удобно проверять существование cookie простым вызовом print_r($_COOKIE);. -
При удалении cookie должны быть заданы те же параметры, что и при
установке. Если в качестве значения задать пустую строку или
FALSE
, а остальные параметры задать соответственно предыдущему вызову, установившему cookie, тогда cookie c заданным именем будет удалено с клиентской машины. Внутренне это выглядит так: cookie присваивается значение 'deleted', а срок действия переносится на год в прошлое. -
Так как установка значения
FALSE
приведет к удалению cookie, не следует задавать cookie значения булевого типа. Вместо этого можно использовать 0 дляFALSE
и 1 дляTRUE
. - Cookie можно именовать, как массивы, и они будут доступны в PHP скрипте, как массивы, но на пользовательской машине они будут храниться в виде отдельных записей. Для задания cookie c множеством имен и значений желательно использовать функцию explode(). Не рекомендуется для этих целей использовать функцию serialize(), так как это негативно сказывается на безопасности скрипта.
При многократных вызовах setcookie() функции выполняются в том порядке, в котором вызывались.
Смотрите также
- header() - Отправка HTTP заголовка
- setrawcookie() - Посылает cookie не преобразовывая значение
- раздел cookies
- » RFC 6265
- » RFC 2109
- checkdnsrr
- closelog
- define_syslog_variables
- dns_check_record
- dns_get_mx
- dns_get_record
- fsockopen
- gethostbyaddr
- gethostbyname
- gethostbynamel
- gethostname
- getmxrr
- getprotobyname
- getprotobynumber
- getservbyname
- getservbyport
- header_register_callback
- header_remove
- header
- headers_list
- headers_sent
- http_response_code
- inet_ntop
- inet_pton
- ip2long
- long2ip
- openlog
- pfsockopen
- setcookie
- setrawcookie
- socket_get_status
- socket_set_blocking
- socket_set_timeout
- syslog
Коментарии
The following code snippet combines abdullah's and Charles Martin's examples into a powerful combination function (and fixes at least one bug in the process):
<?php
function set_cookie_fix_domain($Name, $Value = '', $Expires = 0, $Path = '', $Domain = '', $Secure = false, $HTTPOnly = false)
{
if (!empty($Domain))
{
// Fix the domain to accept domains with and without 'www.'.
if (strtolower(substr($Domain, 0, 4)) == 'www.') $Domain = substr($Domain, 4);
$Domain = '.' . $Domain;
// Remove port information.
$Port = strpos($Domain, ':');
if ($Port !== false) $Domain = substr($Domain, 0, $Port);
}
header('Set-Cookie: ' . rawurlencode($Name) . '=' . rawurlencode($Value)
. (empty($Expires) ? '' : '; expires=' . gmdate('D, d-M-Y H:i:s', $Expires) . ' GMT')
. (empty($Path) ? '' : '; path=' . $Path)
. (empty($Domain) ? '' : '; domain=' . $Domain)
. (!$Secure ? '' : '; secure')
. (!$HTTPOnly ? '' : '; HttpOnly'), false);
}
?>
Basically, if the domain parameter is supplied, it is converted to support a broader range of domains. This behavior may or may not be desireable (e.g. could be a security problem depending on the server) but it makes cookie handling oh-so-much-nicer (IMO).
Note when setting "array cookies" that a separate cookie is set for each element of the array.
On high traffic sites, this can substantially increase the size of subsequent HTTP requests from clients (including requests for static content on the same domain).
More importantly though, the cookie specification says that browsers need only accept 20 cookies per domain. This limit is increased to 50 by Firefox, and to 30 by Opera, but IE6 and IE7 enforce the limit of 20 cookie per domain. Any cookies beyond this limit will either knock out an older cookie or be ignored/rejected by the browser.
something that wasn't made clear to me here and totally confused me for a while was that domain names must contain at least two dots (.), hence 'localhost' is invalid and the browser will refuse to set the cookie! instead for localhost you should use false.
to make your code work on both localhost and a proper domain, you can do this:
<?php
$domain = ($_SERVER['HTTP_HOST'] != 'localhost') ? $_SERVER['HTTP_HOST'] : false;
setcookie('cookiename', 'data', time()+60*60*24*365, '/', $domain, false);
?>
If you want to delete all cookies on your domain, you may want to use the value of:
<?php $_SERVER['HTTP_COOKIE'] ?>
rather than:
<?php $_COOKIE ?>
to dertermine the cookie names.
If cookie names are in Array notation, eg: user[username]
Then PHP will automatically create a corresponding array in $_COOKIE. Instead use $_SERVER['HTTP_COOKIE'] as it mirrors the actual HTTP Request header.
<?php
// unset cookies
if (isset($_SERVER['HTTP_COOKIE'])) {
$cookies = explode(';', $_SERVER['HTTP_COOKIE']);
foreach($cookies as $cookie) {
$parts = explode('=', $cookie);
$name = trim($parts[0]);
setcookie($name, '', time()-1000);
setcookie($name, '', time()-1000, '/');
}
}
?>
Note that the $_COOKIE variable not will hold multiple cookies with the same name. It is legitimate to set two cookies with the same name to the same host where the sub domain is different.
<?php
setcookie("testcookie", "value1hostonly", time(), "/", ".example.com", 0, true);
setcookie("testcookie", "value2subdom", time(), "/", "subdom.example.com", 0, true);
?>
The next request from the browser will have both cookies in the $_SERVER['HTTP_COOKIE'] variable, but only one of them will be found in the $_COOKIE variable. Requests to subdom.example.com will have both cookies, while browser request to example.com or www.example.com only sends the cookie with the "value1hostonly" value.
<?php
$kaker = explode(";", $_SERVER['HTTP_COOKIE']);
foreach($kaker as $val){
$k = explode("=", $val);
echo trim($k[0]) . " => " . $k[1];
}
// output
testcookie => value1hostonly
testcookie => value2subdom
?>
A period in a cookie name (like user.name) seems to show up in the $_COOKIE array as an underscore (so user_name). This means that for example $_COOKIE["user_name"] must be used to read a cookie that has been set with setcookie("user.name" ...), which is already rather confusing.
Furthermore the variable $_COOKIE["user_name"] will retain the value set by setcookie("user.name" ...) and no amount of calling setcookie("user_name" ...) will alter this value. This is rather trivially fixed by clearing the "user.name" cookie, but it can take a while to realize this since there's only "user_name" in $_COOKIE.
Hope this saves someone some time.
Want to remove a cookie?
Many people do it the complicated way:
setcookie('name', 'content', time()-3600);
But why do you make it so complicated and risk it not working, when the client's time is wrong? Why fiddle around with time();
Here's the easiest way to unset a cookie:
setcookie('name', 'content', 1);
Thats it.
Instead of this:
<?php setcookie( "TestCookie", $value, time()+(60*60*24*30) ); ?>
You can this:
<?php setcookie( "TestCookie", $value, strtotime( '+30 days' ) ); ?>
Caveat: if you use URL RewriteRules to get stuff like this: domain.com/bla/stuf/etc into parameters, you might run into a hickup when setting cookies.
At least in my setup a change in one of the parameters resulted in the cookie not being 'there' anymore.
The fix is simple: specify the domain. '/' will usualy do fine.
It's worth a mention: you should avoid dots on cookie names.
<?php
// this will actually set 'ace_fontSize' name:
setcookie( 'ace.fontSize', 18 );
?>
The " PHPSESSID " cookie will soon be rejected because its " sameSite " attribute is set to " none " or an invalid value, and without " secure " attribute. To learn more about the "sameSite" attribute, visit https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie/SameSite.
<?php
ini_set("session.cookie_secure", 1);
session_start();
my PHP code ....
?>
Just an example to clarify the use of the array options, especially since Mozilla is going to deprecate / penalise the use of SameSite = none, which is used by default if not using array options.
<?php
$arr_cookie_options = array (
'expires' => time() + 60*60*24*30,
'path' => '/',
'domain' => '.example.com', // leading dot for compatibility or use subdomain
'secure' => true, // or false
'httponly' => true, // or false
'samesite' => 'None' // None || Lax || Strict
);
setcookie('TestCookie', 'The Cookie Value', $arr_cookie_options);
?>
In any web browser there is a very commonly used option "Open previous windows and tabs" which is disabled by default, but many people enable it.
When this option is active, the web browser, when closing and reopening, instead of executing the termination and starting a new session, saves and restores the current session along with session cookies and sessionStorage.
Both session cookies and sessionStorage, contrary to expectations, can live for a very long time until the user closes the tab before closing the web browser.
If you want a cookie, for example with a time offset, to be guaranteed to have a short lifetime, you should explicitly specify this short lifetime, rather than relying on self-deletion on the session cookie.