PDA

Click to See Complete Forum and Search --> : Storing URLS in a cookie


wwwfilmfilercom
Jan 2nd, 2009, 11:50 AM
Hi

Id like a cookie to store a customers recent items viewed.

Im doing this to set the cookie:

setcookie("viewed", "", time()+3600000);

And then in my list Ive got this:

if (isset($_COOKIE["viewed"])) {
foreach ($_COOKIE["viewed"] as $name => $value)
{
echo "$name : $value <br />";
}
} else {
echo "no cookies";
}


If a user clicks on an item it is meant to add the URL of the item to the cookie array list (after making sure its not already there). Im doing this:

if (isset($_COOKIE["viewed"]))
setcookie("viewed[".$mid."]","$mid");
}


Unfortunately I'm getting the echo statement 'no cookies' so I reckon the setCookie function is wrong, but am I going about this the right way? Ive searched online and not found anything to specifically explain using cookies and then pushing items to the array list.

Can you help?

kows
Jan 3rd, 2009, 02:52 AM
I've not tested anything myself, but you might have trouble setting the cookie as an array because you're not setting the cookie as an array initially (though, I'm not even sure that matters). you could try just setting your cookie using:
setcookie("viewed[$mid]", $mid);
the only other thing that I could see might give you problems is if $mid is storing a full URL, you might characters that need to be escaped. you could use a function for this, but if the name of the key for the cookie doesn't matter to you, you could simply hash the array's key, like below:
$hash = md5($mid);
setcookie("viewed[$hash]", $mid");
if neither solution works, then make sure you're not trying to use setcookie() after you've sent output to the browser.

visualAd
Jan 3rd, 2009, 04:37 AM
First thing to do is set error reporting to its most verbose level. As kows said, you need to ensure that cookies are set before any other output as they are sent in a SetCookie header.

Do this by inserting the following line at the top of your script:

<?php

error_reporting(E_ALL);

?>


If you haven't already got error reporting set to E_ALL I suggest you change it in your php.ini because it will help during development with debugging.

I have never used arrays within cookies before and would not recommend it either. However, I did a quick test in Firefox and IE and both don't seem to mind saving Cookies with [] in their names. What is the typical value of your $mid variable?

My advice however would be to use a session. The session will send a single cookie to the browser containing a session ID and allow you to store as much information relating to that session on the server side as you like (http://www.php.net/session).


session_start(); // like cookies, needs to be called before output

$_SESSION['myarray'] = array(1, 6, 6, 7, 7, 2);

wwwfilmfilercom
Jan 3rd, 2009, 09:48 AM
$mid is just an integer value, 1, 2, 3.

The reason I'm using cookies instead of sessions is that I want the list to remain even if the user visits the site a day or week later.

Would it be a better idea to simply store the data into one cookie and then use explode() to output separate items? " " could be the delimiter?

visualAd
Jan 3rd, 2009, 10:25 AM
The array notation "should" work. But a comma separated list of integer product ids would be better. You will then require only one cookie, so it will reduce the amount of data being sent between the server and client.

wwwfilmfilercom
Jan 3rd, 2009, 12:49 PM
Actually yes, that was exactly the idea - to store the $mid rather than entire url!

Ill test it all again and use error reporting too - thanks!

wwwfilmfilercom
Jan 3rd, 2009, 05:04 PM
How do I set the cookie properly? By this I mean, I want to take $mid and then search through the cookie to ensure it's not already there, if it isn't I want to add it to the cookie and separate all $mid's with the ,comma as you've advised.

How do I do that properly?

visualAd
Jan 3rd, 2009, 06:10 PM
That's three questions - I'll have to start charging :)

To set the cookie, use setcoookie as you were doing before.


The explode() (http://www.php.net/explode) function to get the id's into an array.


Then use the in_array() (http://www.php.net/in_array) function to search for the ID you need.


If it is not there append it to the array and use the implode() (http://www.php.net/implode) function to get change the list. (if you are making no other changes to the array you could just append the id to the end of the original string).


Finally set the cookie with the new string.

wwwfilmfilercom
Jan 3rd, 2009, 06:47 PM
Thanks for that VisualAd! I'll be testing it now; and as for charging well I'm going to rate you!

wwwfilmfilercom
Jan 3rd, 2009, 06:56 PM
setcookie("viewed", "$id", time()+3600000);

Does the above line of code actually set a brand new cookie called 'viewed' or does it add to an existing cookie called 'viewed'?

Each time I change $id will it overwrite the current cookie or make a new one eg. viewed.$id?

wwwfilmfilercom
Jan 3rd, 2009, 07:39 PM
Ok it's fine - this is how I did it, thanks to your code:


/* FIND OUT IF THE COOKIE EXISTS */
if (isset($_COOKIE["viewed"])) {
$viewed=$_COOKIE["viewed"];
// BREAK IT UP AND SEARCH FOR ID
$views = explode(",", $viewed);
if (in_array($id, $views)) {
// DO NOTHING AS IT EXISTS IN LISTS
} else {
// ADD IT TO VIEWS ARRAY
array_push($views, $id);
// JOIN UP ARRAY READY FOR COOKIE LIST
$viewed = implode(",", $views);
// SET IT AS NEW COOKIE VIEWED
setcookie("viewed", $viewed, time()+3600000);
}
} else {
// CREATE NEW RECENTLY-VIEWED COOKIE
setcookie("viewed", $id, time()+3600000);
}


Cheers!

kows
Jan 3rd, 2009, 07:56 PM
it would be better to check if the in_array() returns false (since this is what you want), rather than checking if it returns true and then doing nothing.
if(!in_array($id, $views)){
//do your stuff.
}

visualAd
Jan 4th, 2009, 04:36 AM
Ok it's fine - this is how I did it, thanks to your code:


/* FIND OUT IF THE COOKIE EXISTS */
if (isset($_COOKIE["viewed"])) {
$viewed=$_COOKIE["viewed"];
// BREAK IT UP AND SEARCH FOR ID
$views = explode(",", $viewed);
if (in_array($id, $views)) {
// DO NOTHING AS IT EXISTS IN LISTS
} else {
// ADD IT TO VIEWS ARRAY
array_push($views, $id);
// JOIN UP ARRAY READY FOR COOKIE LIST
$viewed = implode(",", $views);
// SET IT AS NEW COOKIE VIEWED
setcookie("viewed", $viewed, time()+3600000);
}
} else {
// CREATE NEW RECENTLY-VIEWED COOKIE
setcookie("viewed", $id, time()+3600000);
}


Cheers!
Glad you got it working, but you should be indenting your code.

penagate
Jan 4th, 2009, 06:03 PM
it would be better to check if the in_array() returns false (since this is what you want), rather than checking if it returns true and then doing nothing.
Why?

wwwfilmfilercom
Jan 5th, 2009, 03:07 PM
Good question - why?

kows
Jan 5th, 2009, 10:17 PM
why would you check for a clause that you don't care about?

#1
if(in_array($id, $views)){
//do nothing
} else {
$x = 1;
}

vs.

#2
if(!in_array($id, $views)){
$x = 1;
}

now, if you actually had to DO something if in_array() returned true, then the first method would make sense -- otherwise, at least to me, it doesn't.

am I the only one who sees this?!

penagate
Jan 5th, 2009, 10:37 PM
Apparently so... The two constructs are identical.

Sometimes the logic of doing nothing in a particular case, rather than doing something in the opposite case, is simpler to follow.

kows
Jan 5th, 2009, 11:18 PM
yes, they do the same thing (not like I was debating that), but it's more efficient to write the way that I posted (though I don't even think it would be more efficient while executing). I can agree that it may be simpler to follow the other way, though, for sure.. but I've never had any problems following it, so I still prefer excluding the "doing nothing."

visualAd
Jan 6th, 2009, 01:41 PM
When the code is parsed by the interpreter, redundant statements such as that are simply removed. The only way in which that is less efficient is the extra typing required :D