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.)
Related
I have a multidimensional array. The parent array includes items that each item inside is an array with its properties.
insertProduct.php checks everytime I add a new product to the array if the product already exists. If it doesn't it pushes it to the array, if it already exists it finds it and adds +1 to its quantity.
I am trying to create a functionality where pressing a button "Undo" removes the latest addition whether it was a whole product (which means its QTY would be 1 so it removes it altoghether) or if the latest addition was just a QTY increase (from 1 to 2) then remove 1 from the QTY.
However my issue is when I add a product that already exists but is not in the last spot of the array, the QTY does increase as it should be but then the UNDO does not do -1 to this item's QTY.
I don't know if it's alright to post a video but here's the pattern of the problem in a short gif
insertProduct.php
if (isset($_SESSION['myArray'])) {
$inserted_products = $_SESSION['myArray'];
$position = array_search($inserted_product_ean, array_column($inserted_products,0));
//check if new product already exists
if ($position !== false) {
$inserted_products[$position][2] = $inserted_products[$position][2] + 1;
$latest_product = $inserted_products[$position];
$_SESSION['latestProduct'] = $latest_product;
$_SESSION['myArray'] = $inserted_products;
} else {
array_push($inserted_products, $product); //$product is an array of info about the item inserted
$latest_product = $product;
$_SESSION['latestProduct'] = $latest_product;
$_SESSION['myArray'] = $inserted_products;
}
} else {
$latest_product = $product;
$_SESSION['latestProduct'] = $latest_product;
array_push($inserted_products, $product);
$_SESSION['myArray'] = $inserted_products;
}
deleteLastEntry.php
<?php
if (isset($_SESSION['myArray'])) {
$inserted_products = $_SESSION['myArray'];
$inserted_products_length = count($inserted_products);
if ($inserted_products_length > 0){
$latest_product = $_SESSION['latestProduct'];
$qty = $latest_product[2];
if ($qty !== false && $qty > 1) {
$qty = $qty - 1;
$latest_product[2] = $qty;
array_pop($inserted_products);
array_push($inserted_products, $latest_product);
$_SESSION['myArray'] = $inserted_products;
}else{
array_pop($inserted_products);
$_SESSION['myArray'] = $inserted_products;
}
}else{
echo '<div class="error-msg">No products to remove</div>';
}
}
?>
I have this code (in Floral.php) that I was given to me as a shopping cart app which works on one (1) web page; I had to dismember it because of the structure of my web pages and now I'm trying to put it back together so it works with multiple web pages (files):
<?php
session_start();
define("PRODUCTCODE", 0);
define("PRODUCTNAME", 1);
define("QUANTITY", 2);
define("PRICE", 3);
var_dump($_POST);
$action = isset($_POST['action']) ? $_POST['action'] : '';
if($action == 'Recalculate') {
RecalculateCart();
}
else if(isset($_POST['Check Out'])) {
header("Location: "."./customer.php");
}
function RecalculateCart() { // something changed, so recalculate everything
$cart = isset($_SESSION['cart']) ? $_SESSION['cart'] : ''; // get current cart for this session (it's not saved between browser sessions!))
$itemcount = isset($_SESSION['itemcount']) ? $_SESSION['itemcount'] : 0; // get the item count
echo "itemcount from SESSION: " .$itemcount;
for ($i=0; $i < $itemcount; $i++) {
$quantity = $_POST['quantity'.[$i]]; // get quantity of new item
echo "quantity from POST: ".$quantity;
if (empty($quantity)) { // quantity is 'empty' so make it zero (0))
$quantity = 0;
}
else if (($quantity < 0) || (!is_numeric($quantity))) { // validate it
$quantity = 0;
}
$cart[QUANTITY][$i] = intval($quantity); // passed validation, so move it to the cart
}
for ($j=0; $j < $itemcount; $j++) {
$quantity = $cart[QUANTITY] [$j]; // add the quantity of the new item to accumulation
if ($quantity == 0) { // remove item from the cart
$itemcount--;
$curitem = $j;
while(($curitem+1) < count($cart[0])) {
for($k = 0; $k < 4; $k++) {
$cart[$k][$curitem] = $cart[$k][$curitem+1];
$cart[$k] [$curitem+1] = '';
}
$curitem++;
}
}
}
$_SESSION['itemcount'] = $itemcount; // save the item count
$_SESSION['cart'] = $cart; // save cart contents
}
?>
$itemcount is 4, according to the echo, which is correct. $quantity is set in another file and becomes part of $cart (it's from a text field in a form; there is a submit button in that form which does the POST). This is that code (in viewCart.php):
<?php
session_start();
define("PRODUCTCODE", 0);
define("PRODUCTNAME", 1);
define("QUANTITY", 2);
define("PRICE", 3);
$action = isset($_POST['action']) ? $_POST['action'] : '';
if (isset($_POST['productcode'])) {
AddToCart();
}
function AddToCart() {
$cart = isset($_SESSION['cart']) ? $_SESSION['cart'] : '';
$itemcount = isset($_SESSION['itemcount']) ? $_SESSION['itemcount'] : 0;
$cart[PRODUCTCODE][$itemcount] = $_POST['productcode'];
$cart[PRODUCTNAME][$itemcount] = $_POST['productname'];
$cart[QUANTITY][$itemcount] = intval($_POST['quantity']);
$cart[PRICE][$itemcount] = $_POST['price'];
$itemcount = $itemcount + 1;
$_SESSION['cart'] = $cart;
$_SESSION['itemcount'] = $itemcount;
echo "addToCart-itemcount: ".$itemcount;
}
?>
Being a somewhat of a noob at PHP, I am assuming that the POST in the first code segment is correct, except for the fact it's in another file which makes it NOT global in scope. So does the global keyword apply here? and if so, where do I put it? (in which file and which statement)?
You're using incorrect syntax to access the quantity array item:
$quantity = $_POST['quantity'.[$i]];
The [$i] actually creates a new array containing the item $i (using the array syntax introduced in PHP 5.4), and when you try to use it as a string it gets output as just 'Array'. So it evaluates to $_POST['quantityArray']. If you have notices enabled you should see an "Array to string conversion" notice to help you catch this sort of thing.
So simply change it to:
$quantity = $_POST['quantity'.$i];
Or:
$quantity = $_POST["quantity$i"];
BTW, notices can be quite helpful for detecting bugs, so make sure you have them enabled. Either enable display_errors and error_reporting in php.ini or add this to your code (but make sure you only show errors on your local or development server, since reporting them on a production server can be a security risk):
ini_set('display_errors', 1);
error_reporting(E_ALL);
Im getting an undefined offset error. I know why i am getting the error and where it is. What i am trying to work out is how to implement the appropriate error checking to prevent this from happening. The method is currently being called via ajax and thus the error cause's issues with the return of any strings etc.
Following is the class's method being called, its variables are being set vie $_GET.
$id = $_GET['id'];
$product = $_GET['name'];
$price = $_GET['price'];
//check for existing product
for($i = 0; $i <= count($_SESSION['BASKET']); $i++) {
//if product exsits incrent by 1
if($_SESSION['BASKET'][$i]['id'] == $id){
$_SESSION['BASKET'][$i]['amount'] = $_SESSION['BASKET'][$i]['amount'] + 1;
break;
//if doesnt exsist creat product array
} else {
$item = array('id' => $id,'amount' => 1,'product' => $product,'price' => $price);
}
}
if(isset($item)){
//push product to session array
array_push($_SESSION['BASKET'], $item);
}
As you can see the method checks to see if the basket currently contains a product and updates by incrementing the quantity ('amount'). I have a constructer that creates the basket array in the class. The issue occurs when the $_SESSION['BASKET'] is called and is empty but still exists as in :
array (
)
this creates and undefined offset error when checking the id in the if statement as the array technically exists but the offset 0 does not. Any ideas how i can handle this?.
Code changes i a have made that cause the same error
if(isset($_SESSION['BASKET'][$i]) && $_SESSION['BASKET'][$i]['id'] == $id){
I have moved the logic outside the loop and added a bool variable, i can then query this to check if a item was found in the array. This allowed me to create another if statement to check if the sessions values were set rather than checking if the array was created.
$id = $_GET['id'];
$product = $_GET['name'];
$price = $_GET['price'];
$exsist = false;
//check for existing product
for($i = 0; $i <= count($_SESSION['BASKET']); $i++) {
if(isset($_SESSION['BASKET'][$i])){
//if product exsits incrent by 1
if(isset($_SESSION['BASKET'][$i]) && $_SESSION['BASKET'][$i]['id'] == $id){
$_SESSION['BASKET'][$i]['amount'] = $_SESSION['BASKET'][$i]['amount'] + 1;
$exsist = true;
break;
}
}
}
if($exsist != true){
$item = array('id' => $id,'amount' => 1,'product' => $product,'price' => $price);
array_push($_SESSION['BASKET'], $item);
}
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);
}
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;
}