Доступ к $ _COOKIE сразу после setcookie ()

80

Я пытаюсь получить доступ к значению cookie (используя $_COOKIE) сразу после вызова setcookie()функции в PHP. Когда я так делаю, $_COOKIE['uname']не устанавливается. Почему?

Обратите внимание, однако, что $_COOKIE['uname']это устанавливается должным образом при следующем выполнении сценария, например, после обновления страницы.

setcookie('uname', $uname, time() + 60 * 30);
echo "Cookie value: " . $_COOKIE['uname'];
куча
источник
К сожалению, ответы здесь не предлагают решения или предлагают плохие обходные пути, даже принятые, см. Stackoverflow.com/questions/3230133#34465594 .
Витрин
@witrin ваша предоставленная ссылка, похоже, перенаправляет на тот же вопрос / ответ.
trainoasis
Это невозможно. Вы должны «подделать» его, либо установив соответствующие записи в $_COOKIEсебе, либо выполнив перенаправление (на ту же страницу) немедленно.
caw

Ответы:

37

$_COOKIEустанавливается при загрузке страницы из-за отсутствия состояния сети. Если вам нужен немедленный доступ, вы можете установить $_COOKIE['uname']себя или использовать промежуточную переменную.

Например:

if (isset($_COOKIE['uname'])) {
    // get data from cookie for local use
    $uname = $_COOKIE['uname'];
}
else {
    // set cookie, local $uname already set
    setcookie('uname', $uname, time() + 1800);  
}
Джейсон МакКрири
источник
21
это не делает файл cookie доступным до обновления страницы ... см. ответ Марка Бейкера ниже по этому поводу :)
pathfinder
Это не правда. Я сделал предположение, основываясь на коде OP, который они используют $unameв своем скрипте. Тогда как Марк Бейкер использует $_COOKIE['uname']напрямую.
Джейсон МакКрири
1
Мне жаль, что я сказал это немного неправильно. Для моих целей, которые относятся к асинхронному сценарию, установка $ _COOKIE на самом деле не устанавливала файл cookie и не отправляла его обратно в браузер (мне тоже нужен был файл cookie), он только сделал его доступным в моем сценарии. Вам также нужно использовать setcookie (), что делает ответ Марка Бейкера. Кроме того, его код намного короче и полезнее для людей, которые приходят сюда из поиска в Google.
Pathfinder
Пользуюсь setcookie(). Этот ответ может не соответствовать вашим потребностям. Но это не значит, что это неправильно . OP и SO сочли этот ответ полезным.
Джейсон МакКрири
2
Я не понимаю, почему этот ответ помечен как «ответ». Он не объясняет, как использовать cookie напрямую, а предоставленный код похож на тот же опубликованный OP. После setcookie()этого кода невозможно получить доступ$_COOKIE['uname']
Истхар
153

Файл cookie не устанавливается до тех пор, пока ответ не будет отправлен обратно клиенту, и недоступен в вашем PHP до следующего запроса от клиента после этого.

Однако, установив файл cookie в своем скрипте, вы можете:

setcookie('uname', $uname, time()+60*30);
$_COOKIE['uname'] = $uname;
Марк Бейкер
источник
2
Очень простое решение. Благодаря!
dawoodman71
1
Качественный товар. Интересно, как вторая строка устанавливает время истечения срока действия, если оно не прошло?
martinedwards
2
@martinedwards Вторая строка не устанавливает время истечения срока действия .... оно устанавливается на время запроса; точно так же, как значение cookie, переданное с запросом из браузера, существует в течение всего запроса
Марк Бейкер
@MarkBaker Простое решение !! Большое спасибо
Шан
Вы хотите сказать. для доступа к значению cookie необходимо дважды получить доступ к странице (файлу php). 1-й раз для установки cookie и 2-й раз для доступа к установленному cookie. Верный?
Pratik
31

Если вы хотите получить доступ к значению cookie сразу после вызова, setcookie()вы не можете использовать $_COOKIE. Причина этого кроется в природе протокола (см. Https://tools.ietf.org/html/rfc6265 ). При использовании setcookie()он определяет файл cookie, который будет отправлен клиенту вместе с остальными заголовками HTTP (см. Http://php.net/manual/en/function.setcookie.php ). Но $_COOKIEс другой стороны, содержит переменные, переданные текущему скрипту через HTTP-файлы cookie от клиента ( http://php.net/manual/en/reserved.variables.cookies.php ).

Когда вы меняете $_COOKIEпосле вызова setcookie()- как рекомендуют некоторые ответы здесь - он больше не содержит только файлы cookie от клиента. Это может помешать предположениям, сделанным в стороннем коде, используемом в вашем приложении, и может привести к нежелательным эффектам сайта. В общем, это не очень хорошая практика, и это только вариант, когда вызовы setcookie()являются частью вашего собственного кода.

Чистый и прозрачный способ получить значение, установленное setcookie()в том же запросе, - использовать headers_list()(см. Http://php.net/manual/en/function.headers-list.php ) :

function getcookie($name) {
    $cookies = [];
    $headers = headers_list();
    // see http://tools.ietf.org/html/rfc6265#section-4.1.1
    foreach($headers as $header) {
        if (strpos($header, 'Set-Cookie: ') === 0) {
            $value = str_replace('&', urlencode('&'), substr($header, 12));
            parse_str(current(explode(';', $value, 1)), $pair);
            $cookies = array_merge_recursive($cookies, $pair);
        }
    }
    return $cookies[$name];
}
// [...]
setcookie('uname', $uname, time() + 60 * 30);
echo "Cookie value: " . getcookie('uname');

Но обратите внимание, что это не будет работать в PHP CLI (например, PHPUnit). В таком случае вы можете использовать сторонние расширения, такие как XDebug (см. Http://xdebug.org/docs/all_functions#xdebug_get_headers ).

Витрин
источник
6
Здесь только одно реальное решение. Чистый, без модификаций стороннего кода, который может содержать setcookie.
Майкл
1
Я не уверен, почему оператор проголосовал за другое решение, но это правильное решение, которое действительно помогло мне.
ChrisP777
Это 100% единственный ответ, приемлемый для производственной среды. Отличное решение @witrin
skidadon
Не знаю почему, но параметр $ limit explode()для меня не работает, просто возвращает один элемент массива со всей строкой внутри: ideone.com/7SnV9y
NaturalBornCamper 02
5

Вы должны сами установить переменную cookie, если она вам нужна немедленно, к тому времени, когда вы загрузите другую страницу, настоящий cookie будет установлен в результате метода setcookie.

setcookie('name', $value, time()+60*30);
$_COOKIE ['name'] = $value;
Джошуа
источник
1

Мы можем сделать это с помощью вызова AJAX.

Если мы хотим создавать файлы cookie при нажатии кнопки, сначала создайте вызов AJAX для создания файлов cookie, а затем при успешном первом вызове AJAX мы можем вызвать другой AJAX для получения файлов cookie.

    function saveCookie() {
            var base_url = $('#base_url').val();
            var url = base_url + '/index/cookie';
            $.ajax({
                'url': url,
                'type': 'POST',
                'success': function (data) {
                    if (data) {
                        var url = base_url + '/index/get_cookie';
                        $.ajax({
                            'url': url,
                            'type': 'POST',
                            'success': function (response) {
                                var container = $('#show');
                                if (response) {
                                    container.html(response);
                                }
                            }
                        });
                    }
                }
            });
        }

    <button type="button" onclick="saveCookie()">Save Cookie</button>
    <div id="show"></div>
Факирчанд Патидар
источник
Знайте, что даже при хороших намерениях OP требует ответа только PHP. :) Может быть, поэтому у вас отрицательные голоса, я не голосовал против вас.
Máxima Alekz
проголосовали за, потому что это тоже единственный подход, который следует учитывать!
Дхрув Тхаккар,
1

У меня была аналогичная проблема, когда я использовал функцию из включенного файла и решил ее с помощью функции, которая возвращает значение файла cookie и устанавливает файл cookie.

function setCookie($input) {
  setcookie('uname', $input, time() + 60 * 30);
  return $input;
}

if(!isset($_COOKIE['uname'])) {
    $uname  = setCookie($whatever);
} else {
    $uname = $_COOKIE['uname'];
}

echo "Cookie value: " . $uname;
Себастьян Купман
источник
-1

Используя ob_start () и ob_flush (), вы можете отправить файл cookie клиенту и получить его за одно и то же время выполнения. Попробуй это:

ob_start();
setcookie('uname', $uname, time() + 60 * 30);
ob_flush();
echo "Cookie value: " . $_COOKIE['uname'];
Уилл Соареш
источник
Кажется, это не работает (PHP 5.4 с nginx). Не могли бы вы расширить?
Пол Делре
-1

setcookie()Функция вашего скрипта запускается, когда веб-браузер запрашивает страницу в первый раз, в вашем случае перезагрузка. Этот файл cookie хранится в браузере пользователя и недоступен для вашего скрипта, запущенного на сервере, до следующего запроса или, в вашем случае, до следующей перезагрузки.

При следующем запросе браузер отправляет этот файл cookie на сервер, и массив $_COOKIEбудет иметь значение, которое вы изначально установили, и браузер отправил обратно при втором запросе.

Роберт Роша
источник
-3

Я установил константу одновременно с созданием файла cookie

define('CONSTANT', true);
return setcookie('cookiename', 'cookie value goes here', time() + 60 * 60 * 24 * 30, '/');

Тогда я могу немедленно что-то сделать:

if(isset($_COOKIE['cookiename']) || $_COOKIE['cookiename'] || defined('CONSTANT') && CONSTANT)
virtualLast
источник