This is a small test. I set a cookie and then try to access it:
<?php
setcookie("t",0,time()+900);
echo ($_COOKIE['t']+10);
setcookie("t",0,time()-3600);
?>
When I run the code I get an error message as below:
Notice: Undefined index: t in /var/www/x/testcookie.php on line 5
10
Why can't I access the cookie?
It doesn't work that way. setcookie just says "with next http connection tell client (browser) to set this cookie. The browser sends it back in next http connection, if it has not expired yet. Only then it is contained in $_COOKIE array. So you can check that it is set in PHP after next page reload.
Besides in your code second cookie will not be set, because you outputted something to the browser which is forbidden before setcookie function (any header function).
setcookie() defines a cookie to be sent along with the rest of the HTTP headers. Like other headers, cookies must be sent before any output from your script (this is a protocol restriction). This requires that you place calls to this function prior to any output, including and tags as well as any whitespace.
Once the cookies have been set, they can be accessed on the next page
load with the $_COOKIE
you need understand how cookies works. with setcookie you sent header to browser, which tells browser to store cookie. And $_COOKIE superglobal contains cookies which comes from user request headers. so it means that variable which you set with setcookie only be available in $_COOKIE array after refresh, when it comes back with user request headers. And remember that set headers you can only before any output, so second setcookie will not work.
Related
I have this PHP
setcookie('hello', '0', 0, '/389732/');
Why when I run it does it not set a cookie?
I printed the value of $_COOKIE['hello'] out immediately after and it puts out an error because it does not exist.
setcookie documentation spells this out:
Once the cookies have been set, they can be accessed on the next page load with the $_COOKIE ...
Edit: it might be tempting to manually insert that cookie into $_COOKIE yourself, but keep in mind that some frameworks helpfully parse $_COOKIE into other data structures on startup and will not see such hackish changes.
$_COOKIE gets populated when the script first runs. setcookie puts the cookie info in a queue that gets turned into a header when the page returns to the browser.
When the browser requests a new page, it sends the cookie information back to your server and the $_COOKIE variable will be populated.
Because the $_COOKIE is the content of the cookie when the php was called.
I would like to know if there is a way to prevent PHP from sending a cookie when calling session_start().
My use case is for a site optimisation:
(1a) I first open a session/send headers.
(1b) Then generate and output some text content.
(1c) To enhance session read/write I call "session_write_close" as soon as I don't need to write in the session anymore.
(2) Finally I have a post-page rendering process (for stats) that requires a write access to the session. The session is closed, I cannot call session_start() again since it sends a cookie and it's to late for that. This is a computation-heavy process, so I have to do it after the page is sent to the client.
The client already received a session-cookie. So I don't need session_start() to send a new (and redundant) one.
Does someone know a way to intercept the cookie or something similar ? Of course I want to avoid the "Cannot send session cookie - headers already sent". This error is invisible for the user because the page is already renderered but it looks ugly in the logs.
My question seems to be a redundant one, but it is not. I know how headers and content work (send headers first, content after). It's just that PHP does not let me do what I want.
I would like to know if there is a way to prevent PHP from sending a cookie when calling session_start().
Yes there is, by telling PHP to not use cookies for sessions. The PHP setting is session.use_cookies:
ini_set('session.use_cookies', 0); # disable session cookies
session_start();
By default cookies are enabled because they are considered more safe then using URL parameters (see Sessions and securityDocs).
(2) Finally I have a post-page rendering process (for stats) that requires a write access to the session. The session is closed, I cannot call session_start() again since it sends a cookie and it's to late for that. This is a computation-heavy process, so I have to do it after the page is sent to the client.
It's probably possible to tell PHP that the cookie is already set by adding it into the $_COOKIE superglobal arrayDocs. I never experimented with it, but in case you use session_start() and PHP sees that the session cookie has been already set (by the browser, not PHP, $_COOKIE represent the browser cookies), it won't send the headers (again) to set the cookie (which as I understand you is what you want).
Edit: Some test script to play around with:
<?php
header('Content-Type: text/plain;');
echo "Incomming Cookies:\n";
print_r($_COOKIE);
// to simulate that this is a new session, the session cookie is removed
// which makes PHP think it is a new session when invoking session_start()
// unset($_COOKIE['PHPSESSID']);
// run the first session
session_start(); // creates the session cookie (as we don't have one yet)
printf("Session %s has been started: %s\n", session_name(), session_id());
var_dump($_SESSION);
$_SESSION['variable'] = isset($_SESSION['variable']) ? $_SESSION['variable']++ : 0;
session_commit();
printf("Session has been closed, remaining id is: %s\n", session_id());
// visual confirmation that session cookie has been created
echo "Outgoing Cookies:\n";
print_r(headers_list());
// run the second session
ini_set('session.use_cookies', 0); # disable session cookies
session_start();
printf("Second session %s has been started: %s\n", session_name(), session_id());
var_dump($_SESSION);
$_SESSION['2nd-variable'] = isset($_SESSION['2nd-variable']) ? $_SESSION['2nd-variable']++ : 0;
session_commit();
You need to call it with a web-browser (and PHP sessions must be configured to work).
I thought I should mention another great way to prevent the cookie (and the cache limiter) headers from being sent when calling session_start.
The session_start call takes an options array where you can set any of the session. prefix variables, and you can disable these things for just that call.
session_start(array(
'use_cookies' => '0',
'cache_limiter' => ''
));
Note that use_cookies keeps the cookie from being sent, and setting the cache limiter to an empty string keeps it from updating the cache headers (not the best documented feature).
Here are two notices that this will fix (this is helpful when you need to work through multiple sessions).
Warning: session_start(): Cannot send session cookie - headers already sent
and
Warning: session_start(): Cannot send session cache limiter - headers already sent
You can use ob_start() function to buffer the headers/content, you may clear the buffer contents using ob_clean()
I am trying to setup a session management with cookies in PHP.
My code is as follows:
if(empty($_COOKIE )) {
setcookie('session_id', md5(uniqid()), time()+(EXPIRE CONSTANT));
}
$session_id = isset($_COOKIE['session_id']) ? $_COOKIE['session_id'] : 0;
I will then check session_id for 0 and print an error message if cookies are disabled.
This works fine if cookies are really disabled.
The problem is, if a user clears his history the first time he visits
the site he will get the error message even if cookies are enabled.
Anyone have any clues about this ?
Thank you in advance
When you do the setcookie call, the cookies will be sent when the header is output to the browser. This means the cookie won't be available until the next page load (when the client sends the cookie back to the server). This is mentioned in the php manual for setcookie http://php.net/manual/en/function.setcookie.php:
setcookie() defines a cookie to be sent along with the rest of the HTTP headers. Like other headers, cookies must be sent before any output from your script (this is a protocol restriction). This requires that you place calls to this function prior to any output, including and tags as well as any whitespace.
Once the cookies have been set, they can be accessed on the next page load with the $_COOKIE or $HTTP_COOKIE_VARS arrays. Note, superglobals such as $_COOKIE became available in PHP 4.1.0. Cookie values also exist in $_REQUEST.
You won't be able to determine if cookies are enabled/disabled until the page has reloaded (from php). I think you'll have to do this check with javascript, or to stay in php do a redirect after setting the cookie for the first time, something like:
if(empty($_COOKIE)) {
if (isset($_GET['cookieset'])) {
// do error message, cookie should be set
}
setcookie('session_id', md5(uniqid()), time()+(EXPIRE CONSTANT));
header('location: http://mysite.com/index.php?cookieset=1');
exit;
}
$session_id = isset($_COOKIE['session_id']) ? $_COOKIE['session_id'] : 0;
#bencoder : I have done the test on iPad and Chrome/PC : you are right for iPad, you do need to refresh the page before you can read the cookie data, but on Chrome/PC, after deleting all cookies, if you set a new one from PHP, you can perfectly get the values directly on the first page load. Why ? There must be a more precise explanation. Why two different behaviors? Does the order of this output/availability of the data depend on the browser request to the server? Interesting to know...
I am trying to set a cookie for a site if it does not exist. It is not working.
if(isset($_COOKIE['about'])){
$_COOKIE['about'] += 1;
}
if(!isset($_COOKIE['about'])){
setcookie("about", 1, time()+3600);
}
I have also tried
if(empty($_COOKIE['about'])){
setcookie("about", 1, time()+3600);
}
The $_COOKIE superglobal is only available for you to read values from. Writing to it does not update the cookie, since that requires a new Cookie header to be sent to the browser. You would probably be better served by sessions backed by cookies, since PHP allows you to modify the session without explicitly saving/setting the cookie.
You can only read stuff from the $_COOKIE superglobal, try setting it normally:
setcookie("about",$_COOKIE['about']+1,time()+3600);
So all together:
if(isset($_COOKIE['about'])){
$_COOKIE['about'] += 1;
}else{
setcookie("about", 1, time()+3600);
}
Note the else, you've checked before if the cookie isset, so there is no need to check again as either it is or it isn't.
Make sure you have not sent any information to the user yet as the setcookie call is just an alias to header() (but with a specific schema to follow). You may have error output disabled and are missing the message, so it appears to work but is failing in the background.
setcookie should be one of the first calls on your page, up there with starting a session and setting a header.
Here is the simple function that I'm using:
public function control() {
$string = 'lolcheck';
setcookie($string, $string, time() + 120, $this->path, $this->domain);
if (isset($_COOKIE[ $string ])) return true;
else return false;
}
The problem is that it only works when I open the page twice, because it gets the previously set cookie.
Apparently everyone suggest to use this practice, but its not working for me.
Am I missing something?
Cookies do not work that way. When a cookie is set, it is not available (i.e. a corresponding $_COOKIE key exists) until the next request.
What actually happens is:
client sends a requests
server sends a response containing a Set-Cookie response header field
After that the client sends the cookie along with any following request:
client sends a request containing a corresponding Cookie request header field
server registers $_COOKIE key
Per the docs:
Cookies will not become visible until the next loading of a page that the cookie should be visible for. To test if a cookie was successfully set, check for the cookie on a next loading page before the cookie expires. Expire time is set via the expire parameter. A nice way to debug the existence of cookies is by simply calling print_r($_COOKIE);.
If you need it accessible on the same page, use sessions instead, or do a redirect to the same URL after the setcookie call.
Cookies are set / received as part of http headers exchange, so, under usual circumstances are one of the first thing the client (browser) sends / receives. For your problem, the client only knows it's got a cookie to send on the second request.
Using a good Firefox extension like Live HTTP Headers can help you discover which stuff's sent when.