Truy cập $ _COOKIE ngay sau setcookie ()


80

Tôi đang cố gắng truy cập giá trị của cookie (đang sử dụng $_COOKIE) ngay sau khi gọi setcookie()hàm trong PHP. Khi tôi làm như vậy, $_COOKIE['uname']không được thiết lập. Tại sao?

Tuy nhiên, lưu ý rằng điều đó $_COOKIE['uname']được đặt như mong đợi khi thực thi tập lệnh tiếp theo, chẳng hạn như sau khi làm mới trang.

setcookie('uname', $uname, time() + 60 * 30);
echo "Cookie value: " . $_COOKIE['uname'];

Thật không may, các câu trả lời ở đây không đưa ra giải pháp hoặc đề xuất các cách giải quyết không tốt ngay cả khi được chấp nhận, hãy xem stackoverflow.com/questions/3230133#34465594 .
witrin

@witrin liên kết được cung cấp của bạn dường như chuyển hướng đến cùng q / a này.
trainoasis

Điều này là không thể. Bạn phải "giả mạo" nó, bằng cách đặt các mục tương ứng trong $_COOKIEchính bạn hoặc bằng cách thực hiện chuyển hướng (đến cùng một trang) ngay lập tức.
caw

Câu trả lời:


37

$_COOKIEđược đặt khi trang tải, do tính chất không trạng thái của web. Nếu bạn muốn truy cập ngay lập tức, bạn có thể $_COOKIE['uname']tự đặt hoặc sử dụng một biến trung gian.

Ví dụ:

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
điều này không làm cho cookie truy cập trước khi refresh trang ... xem câu trả lời tiếp tục xuống Mark Baker cho rằng :)
pathfinder

Đo không phải sự thật. Tôi đã đưa ra giả định, dựa trên mã của OP, mà họ sử dụng $unametrong tập lệnh của họ. Trong khi Mark Baker sử dụng $_COOKIE['uname']trực tiếp.
Jason McCreary

1
Tôi xin lỗi vì tôi đã nói hơi sai. Đối với mục đích của tôi, đó là cho một tập lệnh không đồng bộ, việc đặt $ _COOKIE không thực sự đặt cookie và gửi nó trở lại trình duyệt (tôi cũng cần cookie ở đó), nó chỉ làm cho nó có sẵn trong tập lệnh của tôi. Bạn cũng cần sử dụng setcookie (), câu trả lời của Mark Baker. Thêm vào đó, mã của anh ấy ngắn hơn rất nhiều và hữu ích hơn cho những người đến đây từ tìm kiếm trên google.
pathfinder

Tôi sử dụng setcookie(). Câu trả lời này có thể không đáp ứng nhu cầu chính xác của bạn. Nhưng điều đó không làm cho nó sai . OP và SO đã tìm thấy câu trả lời này hữu ích.
Jason McCreary

2
Tôi không hiểu tại sao câu trả lời này được đánh dấu là "câu trả lời". Nó không giải thích cách sử dụng cookie trực tiếp và mã được cung cấp giống như mã OP đã đăng. Sau setcookie()mã đó, không thể truy cập$_COOKIE['uname']
Isthar

153

Cookie không được đặt cho đến khi phản hồi được gửi lại cho máy khách và không có sẵn trong PHP của bạn cho đến khi có yêu cầu tiếp theo từ máy khách sau đó.

Tuy nhiên, khi bạn đặt cookie trong tập lệnh của mình, bạn có thể thực hiện:

setcookie('uname', $uname, time()+60*30);
$_COOKIE['uname'] = $uname;

2
Giải pháp rất đơn giản. Cảm ơn!
dawoodman71

1
Công cụ tuyệt vời. Tôi tự hỏi làm thế nào dòng thứ hai đặt thời gian hết hạn khi nó chưa được chuyển vào?
martinedwards

2
@martinedwards Dòng thứ hai không đặt bất kỳ thời gian hết hạn nào .... nó được đặt trong khoảng thời gian yêu cầu; trong chính xác cùng một cách mà một giá trị cookie thông qua với một yêu cầu từ một trình duyệt tồn tại trong suốt thời gian theo yêu cầu
Mark Baker

@MarkBaker Giải pháp đơn giản !! Cảm ơn rất nhiều
Shan

Bạn có ý nói. để truy cập giá trị cookie, Trang (tệp php) cần được truy cập hai lần. Lần đầu tiên để đặt cookie và lần thứ hai để truy cập cookie đã đặt. Chính xác?
Pratik

31

Nếu bạn muốn truy cập giá trị của cookie ngay sau khi gọi giá trị setcookie()mà bạn không thể sử dụng $_COOKIE. Lý do cho điều này là do bản chất của giao thức (xem https://tools.ietf.org/html/rfc6265 ). Khi bạn sử dụng, setcookie()nó xác định một Cookie sẽ được gửi cùng với phần còn lại của tiêu đề HTTP tới máy khách (xem http://php.net/manual/en/ Chức năng.setcookie.php ). Nhưng $_COOKIEmặt khác, chứa các biến được truyền đến tập lệnh hiện tại thông qua HTTP Cookies từ máy khách ( http://php.net/manual/en/reserved.variables.cookies.php ).

Khi bạn thay đổi $_COOKIEsau khi gọi setcookie()- giống như một số câu trả lời ở đây đề xuất - nó không chỉ chứa Cookie từ khách hàng nữa. Điều này có thể can thiệp vào các giả định được thực hiện bằng mã của bên thứ ba được sử dụng trong ứng dụng của bạn và có thể dẫn đến các hiệu ứng trang web không mong muốn. Vì vậy, nói chung, đó không phải là một phương pháp hay và nó chỉ là một lựa chọn khi các lệnh gọi setcookie()là một phần của mã riêng của bạn.

Một cách rõ ràng và minh bạch để nhận giá trị được đặt setcookie()trong cùng một yêu cầu là sử dụng headers_list()(xem http://php.net/manual/en/ Chức năng.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');

Nhưng lưu ý rằng điều này sẽ không hoạt động trong PHP CLI (ví dụ: PHPUnit). Trong trường hợp này, bạn có thể sử dụng các tiện ích mở rộng của bên thứ ba như XDebug (xem http://xdebug.org/docs/all_functions#xdebug_get_headers ).


6
Chỉ có một giải pháp thực sự ở đây. Sạch sẽ, không sửa đổi mã của bên thứ 3 có thể chứa setcookie.
Michael

1
Tôi không chắc tại sao op đã bỏ phiếu cho giải pháp khác, nhưng đây là giải pháp chính xác thực sự đã giúp tôi.
ChrisP777,

Đây 100% là câu trả lời duy nhất khả thi đối với môi trường sản xuất. Giải pháp tuyệt vời @witrin
skidadon

Tôi không biết tại sao, nhưng các tham số $ giới hạn về explode()việc does't đối với tôi, chỉ cần trả một phần tử mảng với toàn bộ bên trong chuỗi: ideone.com/7SnV9y
NaturalBornCamper

5

Bạn phải tự đặt biến cookie nếu bạn cần nó ngay lập tức, vào thời điểm bạn tải một trang khác, cookie thực sẽ được đặt do phương thức setcookie.

setcookie('name', $value, time()+60*30);
$_COOKIE ['name'] = $value;

1

Chúng ta có thể thực hiện việc này bằng cách gọi AJAX.

Nếu chúng ta muốn tạo cookie khi nhấp vào nút, vì vậy trước tiên hãy tạo lệnh gọi AJAX để tạo cookie, sau đó thành công của lệnh gọi AJAX đầu tiên, chúng ta có thể gọi một AJAX khác để lấy 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>

Biết rằng ngay cả khi có ý định tốt, OP yêu cầu câu trả lời chỉ PHP. :) Có lẽ đó là lý do tại sao bạn có phiếu phản đối, tôi đã không phản đối bạn.
Máxima Alekz

ủng hộ vì đây cũng là một cách tiếp cận cần được xem xét!
Dhruv Thakkar

1

Tôi gặp sự cố tương tự khi tôi sử dụng một hàm từ một tệp được bao gồm và giải quyết nó bằng một hàm vừa trả về giá trị của cookie vừa đặt 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

Sử dụng ob_start ()ob_flush (), bạn có thể gửi cookie tới máy khách và truy xuất nó trong cùng một thời gian chạy. Thử cái này:

ob_start();
setcookie('uname', $uname, time() + 60 * 30);
ob_flush();
echo "Cookie value: " . $_COOKIE['uname'];

Điều này dường như không hoạt động (PHP 5.4 w / nginx). Bạn có thể vui lòng mở rộng không?
Paul DelRe

-1

setcookie()Chức năng của script của bạn chạy khi trình duyệt web yêu cầu trang lần đầu tiên, trong trường hợp của bạn là tải lại. Cookie này được lưu trữ trong trình duyệt của người dùng và không có sẵn cho tập lệnh của bạn đang chạy trên máy chủ cho đến khi có yêu cầu tiếp theo hoặc trong trường hợp của bạn là lần tải lại tiếp theo.

Khi có yêu cầu tiếp theo, trình duyệt sẽ gửi cookie đó đến máy chủ và mảng $_COOKIEsẽ có giá trị mà bạn đã đặt ban đầu và trình duyệt gửi lại theo yêu cầu thứ hai.


-3

Tôi đặt một hằng số cùng lúc cookie được tạo

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

Sau đó, tôi có thể ngay lập tức làm điều gì đó bằng cách:

if(isset($_COOKIE['cookiename']) || $_COOKIE['cookiename'] || defined('CONSTANT') && CONSTANT)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.