Unable to set cookie if it does not already exist in PHP - php

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.

Related

Why can't I set a cookie in PHP which can be used in an If statement on the next page?

I'm trying to create a cookie within PHP.
By using the following code :
<?php
//Writing Cookie Data
setcookie("Enabled", "True", time()+3600);
setcookie("Username", $username);
//Test if cookie is set. / Just for test purposes.
echo $_COOKIE["Username"];
?>
After the cookie is set I've used a code to let users go to the next page by pressing an image (link).
This one :
<img src="image.png"></img>
And I've used a code on the next page which will check if the cookie exists.
This one :
<!-- Security Start -->
<?php
If (isset($_COOKIE["Enabled"])) {
}
else
{
header("Location: ../");
}
?>
<!-- Security Stop -->
And when the user goes to the next page he'll just be redirected to the folder specified if the security cookie doesn't exist.
I've probably setup everything correctly, and I've already checked many things, but I can't come up with a solution to this problem. The cookie should exist, and exsists.
Because the echo code works on the same page.
But after going to the next page; the cookie is suddenly gone, it doesn't exist.
Echo and using it in an If statement on the next page are both not possible.
Any ideas what might cause this?
Cookies
Some things I would do to debug this if you want cookies:
I would check the path as stated by Patrick
I would look at the return value of setcookie and see if it tells you it failed.
In your browser you should be able to see a list of all cookies, and you can check and see if the cookie was actually set. Again, look at the path here.
Using a session instead
However, I agree with the session recommendation by developerwjk, one way to do it is to make sure you call 'ob_start()' as one of the first things that happens on the page, it will then buffer the output and give you time to manipulate $_SESSION. Make sure you then call ob_flush(), to flush the buffer once you are finished with all session stuff.. I believe otherwise it will automatically flush the buffer at the end of the page but it might just discard everything..
You do not see the cookie because you have not set the PATH argument for setcookie
Using a path of "/" will enable the use of the cookie anywhere on the domain, otherwise the cookie can only be seen by scripts in the folder and sub folders of the executing script.
setcookie("Enabled", "True", time()+3600, "/");
setcookie("Username", $username,time()+3600,"/");
But as with the comments do not use cookies in place of sessions, as cookies can be easily faked.
If you already have session started you do not need to do session_start() again, if you have php 5.4 or higher you can check session status with session_status
if (session_status() !== PHP_SESSION_ACTIVE) {session_start();}
or if it is lower than 5.4
if (!isset($_SESSION)) { session_start(); }
As per the user submitted comment on the session_status page

Why does this PHP setcookie() argument not set a cookie?

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.

Prevent php session_start() to send a cookie

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 security­Docs).
(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 array­Docs. 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()

Cookies cannot be set the first time after clearing history in Firefox

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...

Can't set PHP cookie on the same page

I'm having trouble setting cookies on the same page. I used cookies on my site and it works fine, I tend to set make the php in separate file. Now, I'm setting a cookie on the same page but it doesn't seem to work.
$expire = time()+5;
setcookie("rb_vote", 1, $expire);
then check if it is set
if(isset($_COOKIE["rb_vote"])) {
echo "IS SET";}
else {
echo "IS NOT SET"; }
It always says is not set. I tried doing this in page load but still doesn't work.
See the manual on setcookie() (emphasis mine):
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
Here is a workaround suggestion. It's imperfect because it can't guarantee the cookie actually gets set, but might do in your case.
I've just encountered this issue in Vanilla Forum. On the first page load, before a session has been established, a session cookie is created, but then every time the application wants to access the session variables (to add to them) it looks for the current session ID in $_COOKIE, which is not set until the next page load.
My workaround is to set the $_COOKIE element manually when the cookie is created.
// Create a cookie to identify the session.
// This line already exists. $Name is the cookie name.
// $SessionID is a random md5 ID that has just been generated.
setcookie($Name, $SessionID, $Expire, $Path, $Domain);
// Set the cookie for the remainder of the page. This is a workaround.
if (!isset($_COOKIE[$Name])) $_COOKIE[$Name] = $SessionID;
I've raised this as a fault with Vanilla (https://github.com/vanillaforums/Garden/issues/1568), as this workaround feels like a bit of a hack, but it certainly gets around the problem for now.
PHP5.3 Vanilla Forum Version 2.0.18.4

Categories