Solved

PHP SetCookie Oddity (PHP)

Posted on 2011-09-14
7
343 Views
Last Modified: 2012-05-12
This is a follow on from an earier post today.
I am having problems creating/writing cookies.

This format works:-
$value2='12';
setcookie('Month',$value2,$inTwoMonths);

This format does not work:
$value2=$_SESSION['Month'];
setcookie('Month',$value2,$inTwoMonths);

Where $_SESSION['Month']; exists and is correct.

As the variables I wish to write as cookies are generated in another page I am moving them around with session varibales. If I do an echo on them they are there and correct.

So how do I enter a session variable as a cookie, or is there another way.

0
Comment
Question by:edhasted
  • 4
  • 3
7 Comments
 
LVL 108

Accepted Solution

by:
Ray Paseur earned 500 total points
Comment Utility
Are you using session_start() before you use $_SESSION?
0
 
LVL 108

Expert Comment

by:Ray Paseur
Comment Utility
Cookies do not have to be "moved around" with session variables.  They are presented to your script in $_COOKIE.  Here is a teaching example that will let you follow the existence of a cookie from cradle to grave.   You can experiment with it here:
http://www.laprbass.com/RAY_cookie_example.php
<?php // RAY_cookie_example.php


// RECEIVE FORM INPUT AND SET A COOKIE WITH THE NAME AND VALUES FROM THE FORM
// MAN PAGE: http://php.net/manual/en/function.setcookie.php
// TO SEE COOKIES IN FIREFOX, FOLLOW SOMETHING LIKE TOOLS => OPTIONS => PRIVACY => SHOW COOKIES (OR "REMOVE INDIVIDUAL")


date_default_timezone_set('America/Chicago');
define('COOKIE_LIFE', 60*60*24); // A 24-HOUR DAY IN SECONDS ( = 86,400 )

// IF THE FORM HAS BEEN POSTED
if (!empty($_POST))
{

    // TIDY UP THE POST INPUT - CLEAN AND NOT MORE THAN 16 BYTES
    $name = substr(clean_string($_POST["name"]),0,16);
    $data = substr(clean_string($_POST["data"]),0,16);

    // BE SURE WE HAVE USEFUL INFORMATION
    if ( ($name == '') || ($data == '') ) die("MISSING INPUT: PLEASE <a href=\"{$_SERVER['PHP_SELF']}\">TRY AGAIN</a>");



    // CHOOSE THE COOKIE NAME AND VALUE
    $cookie_name    = $name;
    $cookie_value   = $data;



    // ESTABLISH THE COOKIE LIFE - CHOOSE ONE OF THESE FOR THE COOKIE
    // USE THIS TO MAKE COOKIE EXPIRE AT END OF BROWSER LIFE
    $cookie_expires = 0;

    // USE THIS TO MAKE A PERSISTENT COOKIE.  DEFINE COOKIE_LIFE IN SECONDS.  date('Z') IS UTC OFFSET IN SECONDS
    $cookie_expires = time() + date('Z') + COOKIE_LIFE;



    // MAKE THE COOKIE AVAILABLE TO ALL DIRECTORY PATHS IN THE WWW ROOT
    $cookie_path	= '/';



    // MAKE THE COOKIE AVAILABLE TO ALL SUBDOMAINS - DOMAIN NAME STARTS WITH DOT AND OMITS WWW (OR OTHER SUBDOMAINS).
    $x = explode('.', strtolower($_SERVER["HTTP_HOST"]));
    $y = count($x);
    if ($y == 1) // MAYBE 'localhost'?
    {
        $cookie_domain = $x[0];
    }
    else // SOMETHING LIKE 'www2.atf70.whitehouse.gov'?
    {
        // USE THE LAST TWO POSITIONS TO MAKE THE HOST DOMAIN
        $cookie_domain = '.' . $x[$y-2] . '.' . $x[$y-1];
    }



    // MAKE THE COOKIE AVAILABLE TO HTTP, NOT JUST HTTPS
    $cookie_secure    = FALSE;



    // HIDE COOKIE FROM JAVASCRIPT (PHP 5.2+)
    $cookie_http      = TRUE;



    // SET THE COOKIE
    if (setcookie($cookie_name, $cookie_value, $cookie_expires, $cookie_path, $cookie_domain, $cookie_secure, $cookie_http))
    {
        echo "<br/>SUCCESS!  THE COOKIE HAS BEEN SET AND WILL BE AVAILABLE TO THE NEXT PAGE LOAD \n";
    }
    else
    {
        echo "<br/>FAILURE!  THE COOKIE WAS NOT SET AS EXPECTED \n";
    }



    // AT THIS POINT, THE COOKIE HAS BEEN SET, BUT IT IS _NOT_ AVAILABLE TO THIS SCRIPT.
    // THE COOKIE WILL NOT BE AVAILABLE TO OUR SERVER UNTIL THE NEXT SCRIPT!
    // THIS IS BECAUSE THE BROWSER SENDS THE COOKIE TO OUR SCRIPT BEFORE OUR SCRIPT STARTS RUNNING.
    echo '<pre>$_COOKIE CONTAINS '; var_dump($_COOKIE); echo "</pre>\n";
    echo '<pre>$_POST CONTAINS ';   var_dump($_POST);   echo "</pre>\n";
    echo "<br/>THE COOKIE HAS BEEN SET WITH THESE VALUES: \n";
    echo "<br/>COOKIE NAME: $cookie_name \n";
    echo "<br/>COOKIE VALUE: $cookie_value \n";
    echo "<br/>COOKIE EXPIRES: $cookie_expires ";
    echo " == " . date('r') . "\n";
    echo "<br/>COOKIE PATH: $cookie_path \n";
    echo "<br/>COOKIE DOMAIN: $cookie_domain \n";
    echo "<br/>COOKIE SECURE: "; var_dump($cookie_secure); echo " \n";
    echo "<br/>COOKIE HTTP: ";   var_dump($cookie_http);   echo " \n";

    echo "<br/>";
    echo "<br/>TO SEE THE COOKIES, IF ANY, <a href=\"{$_SERVER['PHP_SELF']}\">CLICK HERE</a> \n";
    echo "<br/>";
}

// END OF SETTING THE COOKIE - DROP OUT OF PHP INTO HTML TO CREATE THE FORM
?>

<form method="post">
COOKIE NAME: <input name="name" /><br/>
COOKIE DATA: <input name="data" /><br/>
<input type="submit" />
</form>

<?php
// SHOW THE COOKIE ARRAY, IF ANY
echo '<pre>$_COOKIE CONTAINS '; var_dump($_COOKIE); echo "</pre>\n";



// UNRELATED FUNCTION TO FORCE A STRING TO CHARACTERS ONLY
function clean_string($string)
{
    return trim(preg_replace('/[^A-Z0-9_]/i', '', $string));
}

// SHOW THE SCRIPT CODE
// die(highlight_file(__FILE__, TRUE));

Open in new window

0
 

Author Comment

by:edhasted
Comment Utility
Ray, many thanks again, I am reading the example. And the book you suggested is on order.... :-)
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:edhasted
Comment Utility
No I didn't have a session_start() before although the test code that I used the force set the cookies didn't either (weird).

Am reading your notes and running some tests, will probably reply next in around 6 hours.

The reason I want it tio work this way is that I need to force some variables into a javascript app. Once the cookies are written it works. My problem is mechanically, rather than manually, writing the cookies.
0
 
LVL 108

Expert Comment

by:Ray Paseur
Comment Utility
You'll love the book!

One of the things that is kind of odd about $_COOKIE goes something like this.  Your script sets a cookie with setcookie() and the cookie is sent to the client browser.  But the client browser only sends the cookie back to your script when there is a new page load via an HTTP request.  So you write something like setcookie('foo', 'bar') and then look at $_COOKIE and it is not there.  You refresh the page and suddenly $_COOKIE['foo'] == 'bar' -- this kind of thing drives programmers nuts, but it is just the way HTTP cookies work in PHP.  

Not only that, but all instances of the browser share the same cookie jar.  You can go to a web site, log in, and then open a new instance of the browser, either a new window or tab.  Now you log out, and log in as someone else.  Poof - the original instance of the browser got changed, too.  In practice this is pretty rare, but when you're developing a system that depends on cookies (and that includes session cookies) it can be maddening.

The $_COOKIE array is not immutable.  You can put stuff into it within your script.  However on each page load, it will be reset to contain only what the client browser sent to your script.

hope these ideas are useful, ~Ray
0
 

Author Comment

by:edhasted
Comment Utility
Indeed.

The thing that stumped me for at least half a day was the setcookie has to be loaded at the top of a page. Some instructions leave this out, others don't make it clear enough. Technically it's obvious but the set and get commands are written very differently.

I have a load of include files that get triggered to perform the setcookie instructions and then load the relevant pages.

In this instance the issue was me leaving out the session_start(); and apologise for wasting your time on such a stupid ommission.Normally I over insert them :-). What I haven't got my head around is when I always need them.

My code is constructed with a lot of includes to make it easy to bolt pages together. At the start of each page I have a session_start(); but I seem to need to included them in each included file. It surprises me that this insturction isn't carried over into the final assembled page.

With many thanks,

Ed
0
 
LVL 108

Expert Comment

by:Ray Paseur
Comment Utility
session_start() can hardly be considered a "stupid" issue.  In my opinion, PHP should be smart enough that it would make all the external superglobal variables read-only and immutable.  But alas, it does not.

In my programming I have one canonical call to the common.php script.  It is the first line of every program I write.  It loads the framework, classes and functions, etc.  It sets error_reporting(), the timezone constant, connects to the data base and starts the session.  Basically, everything in the development environment is set up with a single line of code.  I do this for two reasons.  One is the "forgetfulness" factor.  If I had to remember many include() scripts I might forget some.  The other is the performance factor.  It is demonstrably faster to load one large script instead of several smaller scripts.  The overhead of file lookups is pretty astonishing.  My pages render in subsecond times (unless I am using an external service like Facebook, but that is a separate issue).  Compare that to any page built on Zend, Drupal, Joomla or Wordpress and you will instantly see why I do it this way.

Thanks for the points and best regards, ~Ray
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Author Note: Since this E-E article was originally written, years ago, formal testing has come into common use in the world of PHP.  PHPUnit (http://en.wikipedia.org/wiki/PHPUnit) and similar technologies have enjoyed wide adoption, making it possib…
These days socially coordinated efforts have turned into a critical requirement for enterprises.
The viewer will learn how to count occurrences of each item in an array.
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now