cookie is being overwritten instead of creating a new one - php

I have written the following piece of code which works fine in Firefox.
// add product
if( isset($_GET['add']) ) {
$pointer = 1;
foreach ($_COOKIE['cart'] as $posit => $value) {
$pointer = $posit+1;
}
setcookie('cart['.$pointer.']', $_GET['add'] , time() + 60*60*24*$cookie_cart , '/' );
header('Location: cart.php');
}
The problem was when I tried it with Safari (so I guess the same problem may happen in other browsers. What happens is when the function foreach() runs, Safari reads the cookies in the opposite order Firefox does, so let's say the following cookies are defined: cart[1], cart[2], cart[3]. Firefox goes in this order, so when I add a new one it is stored as cart[4], whilst Safari does the opposite, making $pointer always be 1+1, storing it as cart[2] every time I add a new product.
I have tried many ways of fixing this, but so far unsuccessfully.
Thanks.

It looks like you don't even need a loop, you could just do
$position = count($_COOKIE['cart'])+1;
setcookie('cart['.$position.']',$_GET['add'] , time() + 60*60*24*$cookie_cart , '/' );
Edit:
Even better would be something like this:
function addItem($id) {
$cart = unserialize($_COOKIE['cart']);
$cart[] = $id;
setcookie('cart', serialize($cart) , time() + 60*60*24*$cookie_cart , '/' );
}
function removeItem($id) {
$cart = unserialize($_COOKIE['cart']);
$cart = array_diff($cart, array($id));
setcookie('cart', serialize($cart) , time() + 60*60*24*$cookie_cart , '/' );
}
function getCart() {
$cart = unserialize($_COOKIE['cart']);
return $cart;
}
And then you can just use those functions to interact with your cart.

For getting the next key, I would something simpler like:
//initial value
$newKey = 0;
//if cart is set and is an array
if(isset($_COOKIE['cart']) && is_array($_COOKIE['cart'])){
//get the max value from the keys and add 1
$newKey = max(array_keys($_COOKIE['cart']))+1;
}

Related

PHP Not Running On Page Until Refresh

bit of a strange one that I've not been able to resolve for months so I finally have given in and have come here for the answer. Hopefully.
I have the below shortcode that when ran returns the phone number depending on what variable has a value. This PHP code works as expected, the one thing that doesn't work as expected however, is the first ever page load.
When someone goes to the site for the first time (or in incognito mode) the shortcode doesn't output anything, however, refresh the page just once and it'll display the output of the correct value and I have no idea why.
<?php function gw_cookie($atts) {
extract(shortcode_atts(array(
"value" => ''
), $atts));
$getVariable = isset($_GET[$value]) ? $_GET[$value] : '';
$newGetVariable = str_replace('_', ' ', $getVariable);
$cookiePhone = isset($_COOKIE[$value]) ? $_COOKIE[$value] : '';
$acfField = get_field('page_cookie_'.$value.'');
$optionsACF = get_field('options_company_details', 'options');
$area = $optionsACF['options_area'];
$phone = $optionsACF['options_telephone'];
if(!empty($cookiePhone) && $cookiePhone !== 'undefined') { //If cookie is not empty do the following
echo '1';
} elseif(!empty($newGetVariable)) { //If cookie is empty and get variable is not
echo '2';
} elseif($acfField) { //If ACF field is not empty do the following
echo '3';
} elseif ($value == "phone") {
return '4';
}
} add_shortcode("gw-cookie", "gw_cookie");
This codes file is being imported into the functions.php file using the following line:
require_once( __DIR__ . '/shortcodes/gw-cookies.php' );
A cookie itself would be created on the first run and your criteria requires cookiePhone which is why you have to refresh to make it work.
As per the comments, change:
$cookiePhone = isset($_COOKIE[$value]) ? $_COOKIE[$value] : '';
to:
$cookiePhone = isset($_COOKIE[$value]) ? $_COOKIE[$value] : NULL;

Cookie is set to null when ran

Let me give you the code first and explain below it:
<?php
$productID = $_POST['productID'];
$productAmount = $_POST['productAmount'];
//Declare variables
$cartNumItems = 0;
//Check if cookie exists and set variable if it does
if(isset($_COOKIE['cart'])){
if($_COOKIE['cart'] != null && $_COOKIE['cart'] != ''){
$cart = $_COOKIE['cart'];
}
}
//Get array from cookie
if(isset($cart)){
//Decode array from $cart variable and store it
$cartArray = json_decode($cart);
//Count number of items in $cart
$cartAmount = count($cartArray);
for($i = 0; $i < $cartAmount; $i++){
//Check if $cart has the same product in it already
if($productID == $cartArray[$i][0]){
//Add to the amount of that product
$cartArray[$i][1] += $productAmount;
break;
}
//If it does not have the same product already, just add a new one
else if($i == ($cartAmount - 1)){
array_push($cartArray, array($productID, $productAmount));
break;
};
};
//Recount number of items in $cart
for($i = 0; $i < $cartAmount; $i++){
$cartNumItems += $cartArray[$i][1];
};
//Encode $cart so it can be stored in cookie
$cartRaw = json_encode($cartArray);
//Create cookies
setcookie('cart', $cartRaw, time() + (86400 * 7), '/');
setcookie('cartNumItems', $cartNumItems, time() + (86400 * 7), '/');
echo 'true';
}
else{
//Create the info that needs to be put into cookie
$cart = json_encode(
array(
array($productID, $productAmount)
)
);
$cartArray = json_decode($cart);
//Count and store the amount of items in cart array
$cartAmount = count($cartArray);
//Store amount of items in $cartNumItems variable
for($i = 0; $i < $cartAmount; $i++){
$cartNumItems += $cartArray[$i][1];
};
//Create cookies
setcookie('cart', $cart, time() + (86400 * 7), '/');
setcookie('cartNumItems', $cartNumItems, time() + (86400 * 7), '/');
echo 'true';
};
?>
When this code is ran the very first time, the "cart" cookie is not set. So it runs the big else statement when checking if the variable "$cart" is set. The else statement works fine and does what it's supposed to. It creates a 2d array, then creates the cookies with the needed information.
The second time the code runs, the if statement should run. Which I believe it does. The "cart" cookie (aka "$cart" variable) is set to null. Then the "cartNumItems" cookie (aka "$cartNumItems" variable) is set to 0. Which it's not supposed to do. I just can't find where it does this, or why it does this.
In case there is any confusion about what specifically is the problem code, this is the problem code (it would seem):
//Get array from cookie
if(isset($cart)){
//Decode array from $cart variable and store it
$cartArray = json_decode($cart);
//Count number of items in $cart
$cartAmount = count($cartArray);
for($i = 0; $i < $cartAmount; $i++){
//Check if $cart has the same product in it already
if($productID == $cartArray[$i][0]){
//Add to the amount of that product
$cartArray[$i][1] += $productAmount;
break;
}
//If it does not have the same product already, just add a new one
else if($i == ($cartAmount - 1)){
array_push($cartArray, array($productID, $productAmount));
break;
};
};
//Recount number of items in $cart
for($i = 0; $i < $cartAmount; $i++){
$cartNumItems += $cartArray[$i][1];
};
//Encode $cart so it can be stored in cookie
$cartRaw = json_encode($cartArray);
//Create cookies
setcookie('cart', $cartRaw, time() + (86400 * 7), '/');
setcookie('cartNumItems', $cartNumItems, time() + (86400 * 7), '/');
echo 'true';
}
Update:
I've found what resets the cookie, this bit of code in the if statement:
//Decode array from $cart variable and store it
$cartArray = json_decode($cart);
When this is ran, $cartArray is set to null, therefore the rest of the code is working off of a null variable. Now what I don't understand is why it's being set to null. when I var_dump the $cart variable I get string(16) "[[\"21\",\"1\"]]". But when I run...
echo json_decode($cart);
It just comes out blank.
[[\"21\",\"1\"]] is not valid JSON, because of the \ characters. Those should not be there in the first place – times of magic_quotes_gpc are gone, unless your PHP version was really old. Remove them, before you call json_decode on the string.
So since you say it doesn’t occur locally, but on your web hoster’s server, it very likely is the setting magic_quotes_gpc that is responsible here (if your PHP version is <= 5.3). If your hoster doesn‘t provide any means to turn it of (custom php.ini, .htaccess), then you can use get_magic_quotes_gpc() to detect it from within your script, and then use f.e. stripslashes to remove them.
(Also check the user comments on the manual page for get_magic_quotes_gpc(), they offer solutions to remove those extra slashes from all external input data via a few lines of scripting.)

PHP Session custom class sessions not being set?

I have a custom class I am writing for easier scripting for myself. I generate life spanned sessions and normal sessions (normal life span). So here's my script parts for creating and getting
CREATE
public static function create($session_name,$value="") {
//check if the $_SESSION was started manually without using our functions...
if(!isset($_SESSION)) {
//init this- it creates session_start session_id
self::init(self::$settings["default_name"]);
}
//create array for serialization
$new_session = array();
//if our session is an array means we want this session to have some unique properties compared to others
if( is_array($session_name)) {
//store the session value in the array
$new_session["value"] = $session_name["value"];
//total time is null, this indicates if we want a life expectancy of total 10 hours total or total from current time.
$total = null;
if(isset($session_name["lifeclock"])) { //lifeclock should be a hh:mm:ss format to be exploded
$clock = explode(":",$session_name["lifeclock"]); //we've exploded it now assign it
$hours = $clock[0]; //hours
$minutes = $clock[1]; //minutes
$seconds = $clock[2]; //seconds
$session_add = 0; //variable to be added to total or not technically
if(isset($session_name["concurrent"])) {
$session_add = time(); //if concurrent time is true assign time to the session_add
}
$total = ( $session_add ) + ((int)$hours * 60 * 60) + ((int)$minutes * 60) + (int)$seconds; //broken down math to make all seconds
}
if(!isset($total)) { //this is why total is null
$total = self::$settings["lifetime"]; //if null lifetime we'll use the default lifetime
}
session_set_cookie_params( $total, //assing all data to the session_set_cookie_params
isset($session_name["path"]) ? $session_name["path"] : self::$settings["path"],
isset($session_name["domain"]) ? $session_name["domain"] : self::$settings["domain"],
isset($session_name["secure"]) ? $session_name["secure"] : self::$settings["secure"],
isset($session_name["httponly"]) ? $session_name["httponly"] : self::$settings["httponly"]
);
$new_session["life"] = $total; //we'll also add the time and when it was born
$new_session["born"] = time(); // so the user can use this later in the programming code
$_SESSION[$session_name["name"]] = serialize($new_session); //serialize the array
} elseif(is_string($session_name)) {
$new_session["value"] = $value; //assign value value
$new_session["born"] = time(); //assign born time
$_SESSION[$session_name] = serialize($new_session); //serialize the array
}
session_write_close(); //close the lock
}
GET
public static function get($session_name,$data = false) {
//test if session has been opened via manual or programatically
if(!isset($_SESSION)) {
self::init(self::$settings["default_name"]);
}
//if data argument is true meaning we don't want all the extra information we'll just return value!
if($data === false) {
if(isset($_SESSION[$session_name])) {
$sess = unserialize($_SESSION[$session_name]);
if(isset($sess["value"])){
return $sess["value"];
} else return false;
} else return false;
} elseif($data === true) {
return unserialize($_SESSION[$session_name]);
}
}
Now here is my file for testing this altogether.
<?php
set_include_path(dirname($_SERVER["DOCUMENT_ROOT"]));
require "admininit__autoload.php";
Session::configure(array(
"default_name"=>"boogie",
"lifetime"=> 3600,
));
Session::create( array(
"name"=>"my_session",
"value"=>"boogie all night long",
"lifeclock"=>"00:05:00"
));
$session_value = Session::get("my_session");
var_dump($session_value);
echo "<pre>";
print_r($_SESSION);
echo "</pre>";
?>
So this is what I get in response to the var_dump and print_r
bool(false)
Array
(
)
So this tells me that $session_value is return false from the get function meaning altogether that the darn session is not saving for some strange reason. Here is what I see in google developers resource panel as well
So to me that's telling me a session is being created somewhere. I've also went ahead and checked my /tmp folder and see no file starting with sess_ which is the usual file for sessions. Any hints as to where my issue lies or maybe flat out what the hell is wrong here?
Update
While the creation of the code is uncommented out I get this
array(1) {
["my_session"]=> string(88) "a:3:{s:5:"value";s:21:"boogie all night long";s:4:"life";i:300;s:4:"born";i:1431562088;}"
}
string(21) "boogie all night long"
Array
(
[my_session] => a:3:{s:5:"value";s:21:"boogie all night long";s:4:"life";i:300;s:4:"born";i:1431562088;}
)
But when I comment out the creation part it returns this
bool(false)
Array
(
)

Drupal Pager is producing POST parameters as part of the URL

I'm not really understanding why this is, but Pager is producing paginated results like the following:
http://www.mywebsite.ca/reports-publications/reports/?field_executive_summary_value=&field_publication_date_value[value]&field_report_type_tid_selective=All&field_natural_resource_region_tid_selective=All&field_forest_district_tid_selective=All&field_keywords_tid_selective=All&page=1#
Instead of simply:
http://www.mywebsite.ca/reports-publications/reports/?page=1
Additionally, "page=1" represents the second page ... as in an array of pages where 0 is actually the first result.
Does anyone know why Pager is producing links like this?
I was able to fix the page number issue by altering pager.inc file.
in pager_find_page function,
function pager_find_page($element = 0) {
$page = isset($_GET['page']) ? $_GET['page'] : '';
$page_array = explode(',', $page);
if (!isset($page_array[$element])) {
// Change here
// $page_array[$element] = 0;
$page_array[$element] = 1;
}
// Add this
$page_array[$element]--;
return (int) $page_array[$element];
}
and, in theme_pager_link function,
if ($new_page = implode(',', pager_load_array($page_new[$element], $element, explode(',', $page)))) {
// Change here
// $parameters['page'] = $new_page;
$parameters['page'] = $new_page + 1;
}

Limit array size in cookie

I have the following function to set a cookie on each indiviual product page a user visits on my website.
function setcookie() {
$entry_id = '787';
if (isset($_COOKIE['recently_viewed'])) {
$currentSession = unserialize($_COOKIE['recently_viewed']);
if (!in_array($entry_id, $currentSession)) {
if (count($currentSession) > 5) {
unset($currentSession[0]);
}
$currentSession[] = $entry_id;
} else {}
$currentSession = serialize($currentSession);
setcookie('recently_viewed', $currentSession, pow(2,31)-1, '/', '');
} else {
$recently_viewed[] = $entry_id;
$currentSession = serialize($recently_viewed);
setcookie('recently_viewed', $currentSession, pow(2,31)-1, '/', '');
}
}
In this function I am trying to limit the number of items stored in the cookies array.
When the cookies array has 6 items in it, I want to remove the first (oldest) item in that array and then add the new item (so there is never more than 6 items, but always adds the new one).
I have used the following, but it doesn't always seem to work. Sometimes it removes the first item when there are more than 5, but other times it just keeps adding them so there are more than 6.
if (count($currentSession) > 5) {
unset($currentSession[0]);
}
Can anyone tell me if there is a better way to achieve this?
You definitely should use session.
session_start();
$entry_id = '788';
if (!is_array($_SESSION['recently_viewed'])) {
$_SESSION['recently_viewed'] = array();
}
// add the item to the begining
array_unshift($_SESSION['recently_viewed'], $entry_id);
// ensure unique entries
$_SESSION['recently_viewed'] = array_unique($_SESSION['recently_viewed']);
// keep first 5 entries
$_SESSION['recently_viewed'] = array_slice($_SESSION['recently_viewed'], 0, 5);
echo 'recent: ' . print_r($_SESSION['recently_viewed'], true);
if (count($currentSession) > 5) {
$arr = array_shift($currentSession);
}

Categories