Jump to content

How to rotate links using php and cookie


mobilestimulus

Recommended Posts

Hello! I'm new here, and this is my first post.

Let's say I have a list of four links I want to display on a page using php, call them 1 2 3 and 4.

Now, when link 2 is visited, or any of the  links, the destination url opens in a new window, a cookie is set onclick and the page reloads, and the visited link goes to the bottom of my list,  and the new the new order is: 1 3 4 2.
 

php function to read cookie and calculate the new order here

echo '<ul>
    <li>
        <a href="https://current-page" onClick="window.open(\'http://page-1\'); setCookie(\''.$cookie_name.'\', \'1\', '.$cookie_expires_time.');">Link One</a>    
    </li>
    <li>
        <a href="https://current-page" onClick="window.open(\'http://page-2\'); setCookie(\''.$cookie_name.'\', \'2\', '.$cookie_expires_time.');">Link Two</a>
    </li>
    <li>
        <a href="https://current-page" onClick="window.open(\'http://page-3\'); setCookie(\''.$cookie_name.'\', \'3\', '.$cookie_expires_time.');">Link Three</a>
    </li>
    <li>
        <a href="https://current-page" onClick="window.open(\'http://page-4\'); setCookie(\''.$cookie_name.'\', \'4\', '.$cookie_expires_time.');">Link Four</a>
    </li>
</ul>';

echo 'some javascript function to enable set cookie on click';

Any help is much appreciated. Thanks.

Link to comment
Share on other sites

You can get the cookie value in PHP using $_COOKIE[$cookie_name].

All those links look the same except for the target and the text. Use an array to hold all four of them.

$links = [
	1 => ["url" => "http://www.example.com/page-1", "text" => "Link One"],
	...
];

Check if the cookie exists. If it does, take the value from it and check if it's one of the keys in $links. If it is, remove that value and put it at the end of the list.

if (isset(/* cookie */)) {
	$id = // value from cookie
	if (isset($links[$id])) {
		$link = // item in $links array
		unset($links[$id]); // remove
		$links[$id] = $link;
	}
}

Finally output the links using a foreach on $links.

Link to comment
Share on other sites

2 hours ago, requinix said:

Use an array to hold all four of them

I appreciate you, and I'm learning. I'm sure I'm getting it wrong, as this is not as expected:

$links = [
    1 => ["url" => "http://www.example.com/page-1", "text" => "Link One"],
    2 => ["url" => "http://www.example.com/page-1", "text" => "Link Two"],
    3 => ["url" => "http://www.example.com/page-1", "text" => "Link Three"],
    4 => ["url" => "http://www.example.com/page-1", "text" => "Link Four"]
];
foreach ( $links as $key => $value )
{
echo "$key=$value<br />";
}

 

Link to comment
Share on other sites

1 hour ago, requinix said:

You are looping over $links. What are going to be the keys in $key and what are going to be the values in $value?

Okay. Thank you so much! Way more helpful than other places for sure! I think I am almost there... What goes here?:

$link = // item in $links array
Link to comment
Share on other sites

@requinix

Okay, again, I'm getting there, slowly, but making progress. Your help is appreciated. However, with each link visit, all that happens is the visited link goes to the bottom of the list. Is that because the cookie doesn't have information about the current order of the list? For instance, on the first visit, I use Link 1, the new order is 2 3 4 1. Now, if i visit link 3 next, the order should now be 2 4 1 3, but instead the order is now 1 2 4 3. Am I still messing up, or do I need to add something else? My code so far:

 

$cookie_name = "link_order_test";
$cookie_expires_time = '1440';
$links = [
    1 => ["url" => "http://www.google.com/", "text" => "Google"],
    2 => ["url" => "https://forums.phpfreaks.com/topic/307814-how-to-rotate-links-using-php-and-cookie/?tab=comments#comment-1561732", "text" => "phpfreaks.com"],
    3 => ["url" => "https://www.w3schools.com/", "text" => "w3schools"],
    4 => ["url" => "http://php.net/manual/en/language.types.array.php", "text" => "php.net"]
];

if(isset($_COOKIE[$cookie_name])) {
    $id = $_COOKIE[$cookie_name];
    if (isset($links[$id])) {
        $link = $links[$id]; // item in $links array
        unset($links[$id]); // remove
        $links[$id] = $link;
    }
} else {
echo 'Cookie Not Found';
}

echo '<ul>';
foreach ( $links as $key => $value )
{
echo '<li><a href="/test/" onClick="window.open(\''.$value[url].'\'); setCookie(\''.$cookie_name.'\', \''.$key.'\', '.$cookie_expires_time.');">'.$value[text].'</a></li>';
}
echo '</ul>';
echo '<a href="/test/" onClick="setCookie(\''.$cookie_name.'\', \'0\', -'.$cookie_expires_time.');">Reset List</a>';
echo '<script>
function setCookie(cname, cvalue, exdays) {
    var d = new Date();
    d.setTime(d.getTime() + (exdays*60*1000));
    var expires = "expires="+d.toUTCString();
    document.cookie = cname + "=" + cvalue + "; " + expires;
}
</script>';

 

Link to comment
Share on other sites

Okay, so you want to keep track of what they visited? That does sound like cookies alright*, but simply knowing the most recent link won't be enough. You need to store all the links... although storing all the links is a hassle, so instead store just the ID numbers of the links.

Rewrite your script a bit:

  • Set up the cookie and link information.
  • Use $_GET["link"] as the way to know the most recently clicked link, instead of the cookie. For the moment you're getting rid of cookies entirely.
  • Change your HTML so that you're passing the link ID through the query string as /test/?link=number. Still no cookies.

Make sure your script continues to work. No cookies for now, but clicking the links should continue to take you back to the same page with the visited link at the bottom of the list. It won't remember like you want, but we're just making sure everything still works with the changes in place.
While you're in there, temporarily put a

setcookie($cookie_name, "", 1);

This will clear out the existing cookie so we can reuse it for something else. Once you've made sure everything is still working, remove that line and you can start on using the cookie again.

This time the cookie will store the entire set of IDs like 1,2,3,4. If the cookie is set then get that string value from it, and if not then use 1,2,3,4 as the default - so not having a cookie is fine. explode that value into an array you can stick in a variable.

Now change your foreach loop so that it goes over that array variable instead of $links. This new variable will only have values in it - its keys are useless. Use each value to get the link information from $links, then to display the link.

* Actually in the Real World we wouldn't use cookies for this.

Link to comment
Share on other sites

@requinix

17 hours ago, requinix said:

This time the cookie will store the entire set of IDs like 1,2,3,4. If the cookie is set then get that string value from it, and if not then use 1,2,3,4 as the default - so not having a cookie is fine. explode that value into an array you can stick in a variable.

I'm having trouble with this part. Can you give me a "push" in the right direction? Here is what I have now:
 

<?php
$link_order = htmlspecialchars($_GET["link_order"]);
$cookie_name = "link_order_test";
$cookie_expires_time = '1440';

$links = [
    1 => ["url" => "http://www.google.com/", "text" => "Google"],
    2 => ["url" => "https://forums.phpfreaks.com/topic/307814-how-to-rotate-links-using-php-and-cookie/?tab=comments#comment-1561732", "text" => "phpfreaks.com"],
    3 => ["url" => "https://www.w3schools.com/", "text" => "w3schools"],
    4 => ["url" => "http://php.net/manual/en/language.types.array.php", "text" => "php.net"]
];

    $id = $link_order;
    if (isset($links[$id])) {
        $link = $links[$id]; // item in $links array
        unset($links[$id]); // remove
        $links[$id] = $link;
    }

$pieces = explode(" ", $links[$key]);
print_r($pieces);
echo '<ul>';
foreach ( $links as $key => $value )
{
echo '<li><a href="/test/?link_order='.$key.'" onClick="window.open(\''.$value[url].'\'); setCookie(\''.$cookie_name.'\', \''.$key.'\', '.$cookie_expires_time.');">'.$value[text].'</a></li>';
}
echo '</ul>';

?>

 

Link to comment
Share on other sites

So I think I have all of the parts here,  just not sure how to implement them. Again, any more help you're willing to give is appreciated. Here is what I have now:

<?php
$link_order = htmlspecialchars($_GET["link_order"]);
$cookie_name = "link_order_test";
$cookie_expires_time = '1440';

if(isset($_COOKIE[$cookie_name])) {
$number_set = $_COOKIE[$cookie_name];
}else{
$number_set = '1,2,3,4';
echo 'Cookie Not Found <br />';
}

$pieces = explode(",", $number_set);

$links = [
    1 => ["url" => "http://www.google.com/", "text" => "Google", "number" => "1"],
    2 => ["url" => "https://forums.phpfreaks.com/topic/307814-how-to-rotate-links-using-php-and-cookie/?tab=comments#comment-1561732", "text" => "phpfreaks.com", "number" => "2"],
    3 => ["url" => "https://www.w3schools.com/", "text" => "w3schools", "number" => "3"],
    4 => ["url" => "http://php.net/manual/en/language.types.array.php", "text" => "php.net", "number" => "4"]
];

foreach ($pieces as $value1) {
    echo "$value1<br>";
}

    $id = $link_order;
    if (isset($links[$id])) {
        $link = $links[$id]; // item in $links array
        unset($links[$id]); // remove
        $links[$id] = $link;
    }

echo '<ul>';

foreach ( $links as $key => $value )
{
echo '<li><a href="/test/?link_order='.$value[number].'" onClick="window.open(\''.$value[url].'\'); setCookie(\''.$cookie_name.'\', \''.$value[number].'\', '.$cookie_expires_time.');">'.$value[text].'</a></li>';
}
echo '</ul>';
if(isset($_COOKIE[$cookie_name])) {
echo '<a href="/test/" onClick="setCookie(\''.$cookie_name.'\', \'0\', -'.$cookie_expires_time.');">Reset List</a>';
}
echo '<script>
function setCookie(cname, cvalue, exdays) {
    var d = new Date();
    d.setTime(d.getTime() + (exdays*60*1000));
    var expires = "expires="+d.toUTCString();
    document.cookie = cname + "=" + cvalue + "; " + expires;
}
</script>';
?>

 

Link to comment
Share on other sites

Let's trim off some of the older code and get something simple that won't do everything you need yet.

<?php

// cookie information
$cookie_name = "link_order_test";
$cookie_expires_time = 1440;

// links
$links = [
	1 => [
		"url" => "http://www.google.com/",
		"text" => "Google"
	],
	2 => [
		"url" => "https://forums.phpfreaks.com/topic/307814-how-to-rotate-links-using-php-and-cookie/?tab=comments#comment-1561732",
		"text" => "phpfreaks.com"
	],
	3 => [
		"url" => "https://www.w3schools.com/",
		"text" => "w3schools"
	],
	4 => [
		"url" => "http://php.net/manual/en/language.types.array.php",
		"text" => "php.net"
	]
];

// list of links to use from the cookie
if (isset($_COOKIE[$cookie_name])) {
	$number_set = $_COOKIE[$cookie_name];
} else {
	$number_set = '1,2,3,4';
}

$pieces = explode(",", $number_set);

// loop to show the links
echo '<ul>';
foreach ($pieces as $number) {
	$value = $links[$number];
	echo '<li><a href="/test/?link_order=' . $number . '" onClick="window.open(\'' . $value["url"] . '\');">' . $value["text"] . '</a></li>';
}
echo '</ul>';

?>

1. I removed the "number" from $links because you already have the number: it's the array key
2. It's not shuffling $links yet but it does get $number_set
3. Nothing to set the cookie
4. Using $pieces to control the order of what links to show
5. Quotes with $value["url"] and $value["text"] because the key in there is a string, not a number, and strings need quotes

If you look at the page in your browser it seems like it might work because it will open the popup and reload the page, but it doesn't change the links. Add that in next.

<?php

$pieces = explode(",", $number_set);
$pieces = array_combine($pieces, $pieces);

// update if there is an update to make
if (isset($_GET["link_order"])) {
	$link_order = $_GET["link_order"];
	if (isset($pieces[$link_order])) {
		unset($pieces[$link_order]);
		$pieces[$link_order] = $link_order;
	}
}

?>

This is a little different from before. $pieces is going to control what links show in what order, and to rearrange what's in it in the easiest way it helps to have the numbers as keys - so isset() will work. array_combine will do that by creating a new array using one with keys and one with values, and with $pieces as both we get an array like [1=>1, 2=>2, 3=>3, 4=>4].

With that the first time we'll be back to having the page update for the link you click but not remembering earlier clicks. That's because we aren't doing anything with the cookie. So now do that. But instead of changing the cookie in Javascript on the client, have PHP do it on the server. That is where cookies are normally handled.

<?php

if (isset($_GET["link_order"])) {
	...

	$number_set = implode(",", $pieces); // array back into string
	setcookie($cookie_name, $number_set, time() + $cookie_expires_time);
}

?>

Note that setcookie() wants the expiration time as a (future) point in time, not a duration.

Link to comment
Share on other sites

@requinix Alright. So, I don't understand what is happening yet, but I will put some more time into learning about it. In the meantime, are you saying that I should now be here?:
 

<?php

// cookie information
$cookie_name = "link_order_test";

// cookie expires 2 minutes from page load
$cookie_expires_time = 120;

// links
$links = [
    1 => [
        "url" => "http://www.google.com/",
        "text" => "Google"
    ],
    2 => [
        "url" => "https://forums.phpfreaks.com/topic/307814-how-to-rotate-links-using-php-and-cookie/?tab=comments#comment-1561732",
        "text" => "phpfreaks.com"
    ],
    3 => [
        "url" => "https://www.w3schools.com/",
        "text" => "w3schools"
    ],
    4 => [
        "url" => "http://php.net/manual/en/language.types.array.php",
        "text" => "php.net"
    ]
];

// list of links to use from the cookie
if (isset($_COOKIE[$cookie_name])) {
    $number_set = $_COOKIE[$cookie_name];
} else {
    $number_set = '1,2,3,4';
}

$pieces = explode(",", $number_set);
$pieces = array_combine($pieces, $pieces);

// update if there is an update to make
if (isset($_GET["link_order"])) {
    $link_order = $_GET["link_order"];
    if (isset($pieces[$link_order])) {
        unset($pieces[$link_order]);
        $pieces[$link_order] = $link_order;
    }

    $number_ set = implode(",", $pieces); // array back into string
    setcookie($cookie_name, $number_set, time() + $cookie_expires_time);
}

// loop to show the links
echo '<ul>';
foreach ($pieces as $number) {
    $value = $links[$number];
    echo '<li><a href="/test/?link_order=' . $number . '" onClick="window.open(\'' . $value["url"] . '\');">' . $value["text"] . '</a></li>';
}
echo '</ul>';

?>

 

Link to comment
Share on other sites

Ha! Yes. An extra space....Fixed. Still not as expected however. Do I need to do more yet? Code as of now:
 

<?php

// cookie information
$cookie_name = "link_order_test";

// cookie expires 2 minutes from page load
$cookie_expires_time = 120;

// links
$links = [
    1 => [
        "url" => "http://www.google.com/",
        "text" => "Google"
    ],
    2 => [
        "url" => "https://forums.phpfreaks.com/topic/307814-how-to-rotate-links-using-php-and-cookie/?tab=comments#comment-1561732",
        "text" => "phpfreaks.com"
    ],
    3 => [
        "url" => "https://www.w3schools.com/",
        "text" => "w3schools"
    ],
    4 => [
        "url" => "http://php.net/manual/en/language.types.array.php",
        "text" => "php.net"
    ]
];

// list of links to use from the cookie
if (isset($_COOKIE[$cookie_name])) {
    $number_set = $_COOKIE[$cookie_name];
} else {
    $number_set = '1,2,3,4';
}

$pieces = explode(",", $number_set);
$pieces = array_combine($pieces, $pieces);

// update if there is an update to make
if (isset($_GET["link_order"])) {
    $link_order = $_GET["link_order"];
    if (isset($pieces[$link_order])) {
        unset($pieces[$link_order]);
        $pieces[$link_order] = $link_order;
    }

    $number_set = implode(",", $pieces); // array back into string
    setcookie($cookie_name, $number_set, time() + $cookie_expires_time);
}

// loop to show the links
echo '<ul>';
foreach ($pieces as $number) {
    $value = $links[$number];
    echo '<li><a href="/test/?link_order=' . $number . '" onClick="window.open(\'' . $value["url"] . '\');">' . $value["text"] . '</a></li>';
}
echo '</ul>';

?>

 

Link to comment
Share on other sites

1. XSS is about what happens with output. You aren't using that value with output so there is no risk of injection.
2. htmlspecialchars() should only be used right when something is about to be outputted. Not any earlier, and definitely not when you first get the value from the user/cookie/wherever.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.