Dostęp do $ _COOKIE natychmiast po setcookie ()

80

Próbuję uzyskać dostęp do wartości pliku cookie (używając $_COOKIE) natychmiast po wywołaniu setcookie()funkcji w PHP. Kiedy to robię,$_COOKIE['uname'] nie jest ustawione. Czemu?

Należy jednak pamiętać, że $_COOKIE['uname']jest to ustawiane zgodnie z oczekiwaniami po następnym wykonaniu skryptu, na przykład po odświeżeniu strony.

setcookie('uname', $uname, time() + 60 * 30);
echo "Cookie value: " . $_COOKIE['uname'];
heapzero
źródło
Niestety odpowiedzi tutaj nie oferują rozwiązania ani nie sugerują złych obejść, nawet zaakceptowanych, patrz stackoverflow.com/questions/3230133#34465594 .
witrin
@witrin, który podałeś, wydaje się przekierowywać do tego samego pytania / odpowiedzi.
trainoasis
To jest niemożliwe. Musisz to „sfałszować”, albo ustawiając w $_COOKIEsobie odpowiednie wpisy, albo wykonując natychmiastowe przekierowanie (na tę samą stronę).
krakaj

Odpowiedzi:

37

$_COOKIEjest ustawiana podczas ładowania strony ze względu na bezpaństwowy charakter sieci. Jeśli chcesz uzyskać natychmiastowy dostęp, możesz ustawić $_COOKIE['uname']siebie lub użyć zmiennej pośredniej.

Na przykład:

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);  
}
Jason McCreary
źródło
21
to nie sprawia, że ​​plik cookie jest dostępny przed odświeżeniem strony ... zobacz odpowiedź Marka Bakera w dalszej części :)
pathfinder
To nieprawda. Zrobiłem założenie, opierając się na kodzie OP, którego używają $unamew swoim skrypcie. Podczas gdy Mark Baker używa $_COOKIE['uname']bezpośrednio.
Jason McCreary
1
Przepraszam, że powiedziałem to trochę źle. Dla moich celów, które są dla skryptu asynchronicznego, ustawienie $ _COOKIE w rzeczywistości nie ustawiało pliku cookie i nie wysyłało go z powrotem do przeglądarki (tam też potrzebowałem pliku cookie), a jedynie udostępniło go w moim skrypcie. Musisz także użyć setcookie (), co robi odpowiedź Marka Bakera. Dodatkowo jego kod jest dużo krótszy i bardziej przydatny dla osób przychodzących tu z wyszukiwarki Google.
pathfinder
Używam setcookie(). Ta odpowiedź może nie odpowiadać dokładnie Twoim potrzebom. Ale to nie czyni tego źle . OP i SO uznali tę odpowiedź za przydatną.
Jason McCreary
2
Nie rozumiem, dlaczego ta odpowiedź jest oznaczona jako „odpowiedź”. Nie wyjaśnia, jak bezpośrednio korzystać z pliku cookie, a podany kod jest taki sam, jak opublikowany OP. Po setcookie()tym kodzie dostęp nie jest możliwy$_COOKIE['uname']
Isthar
153

Plik cookie nie jest ustawiany, dopóki odpowiedź nie zostanie wysłana z powrotem do klienta i nie jest dostępny w twoim PHP do następnego żądania od klienta.

Jeśli jednak ustawisz plik cookie w swoim skrypcie, możesz:

setcookie('uname', $uname, time()+60*30);
$_COOKIE['uname'] = $uname;
Mark Baker
źródło
2
Bardzo proste rozwiązanie. Dzięki!
dawoodman71
1
Świetne rzeczy. Zastanawiam się, jak druga linia ustawia czas wygaśnięcia, gdy nie jest przekazywana?
martinedwards
2
@martinedwards Druga linia nie ustawia żadnego czasu wygaśnięcia… jest ustawiony na czas trwania żądania; dokładnie w ten sam sposób, w jaki wartość cookie przekazana z żądaniem z przeglądarki istnieje na czas trwania żądania
Mark Baker
@MarkBaker Simple Solution !! Wielkie dzięki
Shan
Chcesz powiedzieć. aby uzyskać dostęp do wartości cookie, należy uzyskać dostęp do strony (pliku php) dwukrotnie. Pierwszy raz, aby ustawić plik cookie, a drugi raz, aby uzyskać dostęp do ustawionego pliku cookie. Poprawny?
Pratik
31

Jeśli chcesz uzyskać dostęp do wartości pliku cookie natychmiast po wywołaniu setcookie(), nie możesz użyć $_COOKIE. Przyczyną tego jest natura protokołu (patrz https://tools.ietf.org/html/rfc6265 ). Kiedy setcookie()go używasz , definiuje plik cookie, który ma być wysłany wraz z resztą nagłówków HTTP do klienta (patrz http://php.net/manual/en/function.setcookie.php ). Ale $_COOKIEz drugiej strony zawiera zmienne przekazywane do aktualnego skryptu przez pliki cookie HTTP od klienta ( http://php.net/manual/en/reserved.variables.cookies.php ).

Kiedy zmieniasz się $_COOKIEpo wywołaniu setcookie()- jak zalecają niektóre odpowiedzi tutaj - nie zawiera już tylko plików cookie od klienta. Może to kolidować z założeniami przyjętymi w kodzie strony trzeciej używanym w Twojej aplikacji i może powodować niepożądane efekty na stronie. Więc ogólnie nie jest to dobra praktyka i jest to opcja tylko wtedy, gdy wywołania setcookie()są częścią twojego własnego kodu.

Czystym i przejrzystym sposobem uzyskania wartości ustawionej w setcookie()ramach tego samego żądania jest użycie headers_list()(patrz 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');

Ale zauważ, że to nie zadziała w PHP CLI (np. PHPUnit). W takim przypadku możesz użyć rozszerzeń innych firm, takich jak XDebug (patrz http://xdebug.org/docs/all_functions#xdebug_get_headers ).

witrin
źródło
6
Tylko jedno prawdziwe rozwiązanie. Czysty, bez modyfikacji kodu firm trzecich, który może zawierać setcookie.
Michael
1
Nie jestem pewien, dlaczego op zagłosował za innym rozwiązaniem, ale to jest właściwe rozwiązanie, które faktycznie mi pomogło.
ChrisP777
To w 100% jedyna odpowiedź, która jest możliwa do zastosowania w środowisku produkcyjnym. Świetne rozwiązanie @ Witrin
skidadon
Nie wiem dlaczego, ale parametr $ limit on explode()nie działa dla mnie, po prostu zwraca jeden element tablicy z całym ciągiem w środku: ideone.com/7SnV9y
NaturalBornCamper
5

Musisz samodzielnie ustawić zmienną cookie, jeśli potrzebujesz jej od razu, zanim załadujesz inną stronę, prawdziwy plik cookie zostanie ustawiony w wyniku metody setcookie.

setcookie('name', $value, time()+60*30);
$_COOKIE ['name'] = $value;
Joshua
źródło
1

Możemy to zrobić za pomocą połączeń AJAX.

Jeśli chcemy tworzyć pliki cookie za pomocą przycisku, więc najpierw utwórz wywołanie AJAX do tworzenia plików cookie, a następnie po powodzeniu pierwszego połączenia AJAX możemy wywołać inny AJAX w celu pobrania plików 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>
Fakirchand Patidar
źródło
Wiedz, że nawet jeśli intencje są dobre, OP wymaga odpowiedzi tylko w PHP. :) Może dlatego masz głosy przeciw, a ja cię nie przegłosowałem.
Máxima Alekz
przegłosowano, ponieważ jest to również jedno podejście, które należy wziąć pod uwagę!
Dhruv Thakkar
1

Miałem podobny problem, gdy użyłem funkcji z dołączonego pliku i rozwiązałem go za pomocą funkcji, która zarówno zwraca wartość pliku cookie, jak i ustawia plik 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;
Sebastiaan Koopman
źródło
-1

Używając ob_start () i ob_flush () możesz wysłać plik cookie do klienta i pobrać go w tym samym czasie wykonywania. Spróbuj tego:

ob_start();
setcookie('uname', $uname, time() + 60 * 30);
ob_flush();
echo "Cookie value: " . $_COOKIE['uname'];
Will Soares
źródło
To wydaje się nie działać (PHP 5.4 z nginx). Czy możesz rozszerzyć?
Paul DelRe
-1

Twój scenariusz setcookie()Funkcja działa, gdy przeglądarka internetowa żąda strony po raz pierwszy, w twoim przypadku przeładowanie. Ten plik cookie jest przechowywany w przeglądarce użytkownika i nie jest dostępny dla Twojego skryptu działającego na serwerze do następnego żądania lub w Twoim przypadku do ponownego załadowania.

Przy następnym żądaniu przeglądarka wysyła ten plik cookie na serwer, a tablica $_COOKIEbędzie miała początkowo ustawioną wartość, a przeglądarka odeśle z powrotem przy drugim żądaniu.

Robert Rocha
źródło
-3

Ustawiłem stałą w tym samym czasie, gdy plik cookie był tworzony

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

Mogę wtedy od razu coś zrobić poprzez:

if(isset($_COOKIE['cookiename']) || $_COOKIE['cookiename'] || defined('CONSTANT') && CONSTANT)
virtualLast
źródło