Search code examples
phpsessiondeep-copystoring-data

The object stored into a PHP session gets the wrong value stored


I have created a shopping cart object that works. But when I try to save the object into the session the wrong content of that object is stored. The value that is being saved is the value after the object is cleared from the shopping cart, the empty one.

    <!doctype html>
<html lang="en">
<head>
 <meta charset="utf-8">
 <title>Testing the Shopping Cart</title>
</head>
<body>
<?php # cart.php
// This script uses the ShoppingCart and Item classes.
//error_reporting(0);
// Create the cart:
session_start();
try {

require('ShoppingCart.php');
require('userMenu.php');
$cart = new ShoppingCart();

// Create some items:
require('Item.php');
require ('Connect.php');

$conn=Connect::doConnect();

$query = "SELECT product_id, product_name, product_price from product";
$result = mysqli_query($conn, $query);
$i=0;
$w = array();
$new_cart;
if ($result->num_rows > 0) {
    // output data of each row
    echo '<table border='."1".'><form action="cart.php" method="post"><tr><td>';
    echo '<b>'."Id produs".'</td><td><b>'."Denumire".'</td><td><b>'."Pret".'</td><td>'."Numar de bucati solicitate".'</td></tr><tr>';
    while($row = $result->fetch_assoc()) {
        echo '<td>'.$row["product_id"].'</td><td>'. $row["product_name"].'</td><td>'. $row["product_price"]. '</td><td>
            <input type="input" value="0" name="quantity[]"><input type="hidden" value="'.$row["product_id"].'" name="item_adjust[]"></td>';
        echo '</tr>';
        $i++;
        $w[$i]=new Item($row["product_id"], $row["product_name"],$row["product_price"]);
        $cart->addItem($w[$i]);
        //$cart->deleteItem($w[$i]);    

    }
    echo '</td></tr><tr><td colspan="3"><input type="submit" value="Adauga in cosul de cumparaturi" name="adjQ"></td></tr></table>';
    //foreach ()

} else {
    echo "0 results";
}
$conn->close();

if($_POST["adjQ"]){

echo "In stoc avem ".$i." tipuri de produse";

// Update some quantities:
$cart_items_new = array_combine($_POST['item_adjust'],$_POST['quantity']);
foreach ($cart_items_new as $product_id=>$quantity){
    //$item=new Item($product_id,Item->);
    //Item $it;
    //->updateItem($item->getId($product_id), $qty);
    //$cart->updateItem(getId($product_id), $quantity);

    $conn=Connect::doConnect();

    $query1 = "SELECT product_id, product_name, product_price from product where 
    product_id='$product_id'";
    $result1 = mysqli_query($conn, $query1);
    $row1=mysqli_fetch_array($result1);

    if($quantity>0){
     $cart->updateItem($w[$product_id], $quantity);
        echo $product_id.$quantity."+".$row1["product_name"];
    }
    else{
        $cart->deleteItem($w[$product_id]);
    }


}


// Show the cart contents:
echo '<h2>Continutul cosului de cumparaturi (' . count($cart) . ' tipuri de produse)</h2>';
echo "The user is " . $_SESSION["user"] . ".<br>";
echo "User type is " . $_SESSION["user_type"] . ".";
$new_cart = unserialize(serialize($cart));
if (!$cart->isEmpty()) {

    foreach ($cart as $arr) {

        // Get the item object:
        $item = $arr['item'];

        // Print the item:
        printf('<p><strong>%s</strong>: %d @ $%0.2f bucata.<p>', $item->getName(), $arr['qty'], $item->getPrice());

    } // End of foreach loop!

} // End of IF.
}

echo '</td></tr><tr><td colspan="2"><input type="submit" value="Salveaza" name="session"></td><td></td></tr></form></table>';
if ($_POST['session'])
{
    echo "You entered the number ";
    $serialize_cart=serialize($new_cart);
    $_SESSION["cart"]=$serialize_cart;
 }

} 

catch (Exception $e) {

}
?>
</body>
</html>

What I am doing wrong when I push the second submit button.


Solution

  • Hey I've had a go at this I can't test it as I dont have the additional files and cart object but it should be close to error free

    I've got a Session variable 'cart' if present we grab it unserialize and were done then can edit the values and save it back out so on

    If not present i.e. first hit or cart was deleted we build a new cart from the database (This isnt ideal just for testing as presently your adding every item from the database to the cart?)

    If the post or get value of adjQ is present we modify some of the values of the cart object and save it back out to the session variable

    If the post or get value of showCart is present we output the current cart To make this work you might have to tweak your Shopping_Cart Object to support the variables being called and the getCount function and the getAllRows function

    I've removed the additional storage of an array of the items from the cart (w) not sure what thats for since you have the data stored in the object dont need to replicate it

    All the request variables should be sanitized to prevent injection attacks n so on

    I've added a hidden field to trigger the showCart request

    Anyway hope this helps

    <?php
        session_start();
    ?>
    <!doctype html>
    <html lang="en">
        <head>
            <meta charset="utf-8">
            <title>Testing the Shopping Cart</title>
        </head>
        <body>
    <?php # cart.php
    // This script uses the ShoppingCart and Item classes.
    //error_reporting(0);
    
        // Create the cart:
        require('ShoppingCart.php');
        require('userMenu.php');
    
        $rowCount = 0;
    
        if(isset($_SESSION['cart']))
        {
            echo "We have a stored cart in a Session variable, retrieving data ...";
    
            $cart = unserialize($_SESSION["cart"]);
    
            $rowCount = $cart->getCount();
        }
        else
        {
            $cart = new ShoppingCart();
    
            // Create some items:
            require('Item.php');
            require ('Connect.php');
    
            $conn=Connect::doConnect();
    
            $query = "SELECT product_id, product_name, product_price from product";
            $result = mysqli_query($conn, $query);
    
            $rowCount = $result->num_rows;
    
            if ($result->num_rows > 0) {
                // output data of each row
                while($row = $result->fetch_assoc()) {
                    $cart->addItem(new Item($row["product_id"], $row["product_name"],$row["product_price"]));
                }
            }
            $conn->close();
        }
    
        if(isset($_REQUEST['adjQ']))
        {
            echo "In stoc avem ".$rowCount." tipuri de produse";
    
            // Update some quantities:
            $cart_items_new = array_combine($_POST['item_adjust'], $_POST['quantity']);
            foreach ($cart_items_new as $product_id=>$quantity) {
                if($quantity > 0) {
                    $cart->updateItem($product_id, $quantity);
    
                    $conn=Connect::doConnect();
    
                    $query1 = "SELECT product_id, product_name, product_price from product where product_id='$product_id'";
                    $result1 = mysqli_query($conn, $query1);
    
                    $row1 = mysqli_fetch_array($result1);
                    echo $product_id." ".$quantity." + ".$row1["product_name"];
                }
                else {
                    $cart->deleteItem($product_id);
                }
            }
    
            // Show the cart contents:
            echo '<h2>Continutul cosului de cumparaturi (' . $rowCount . ' tipuri de produse)</h2>
            The user is ' . $_SESSION["user"] . '.<br>
            User type is ' . $_SESSION["user_type"] . '.';
    
            if (!$cart->isEmpty()) {
                foreach ($cart as $arr) {
                    // Get the item object:
                    $item = $arr['item'];
                    // Print the item:
                    printf('<p><strong>%s</strong>: %d @ $%0.2f bucata.<p>', $arr['item']->getName(), $arr['item']->getQuantity(), $arr['item']->getPrice());
                } // End of foreach loop!
    
                echo "Saving card to Session variable";
                //New_cart is only set in adjQ request prehaps this code should be there?
                $_SESSION["cart"] = serialize($cart);
            } // End of IF.
        }
    
        if(isset($_REQUEST['showCart']))
        {
            if ($cart->getCount() > 0) {
                // output data of each row
                echo '<table border='."1".'><form action="cart.php" method="post">';
                echo '<tr><td><b>'."Id produs".'</td><td><b>'."Denumire".'</td><td><b>'."Pret".'</td><td>'."Numar de bucati solicitate".'</td></tr>';
                foreach ($cart->getAllRows() as $row) {
                    echo '
                        <tr>
                            <td>'. $row->getProductId() . '</td>
                            <td>'. $row->getName() . '</td>
                            <td>'. $row->getPrice() . '</td>
                            <td><input type="input" value="0" name="quantity[]"><input type="hidden" value="' . $row->getProductId() . '" name="item_adjust[]"/><input type="hidden" value="showCart" name="showCart"/></td>
                        </tr>';
                }
                echo '<tr><td colspan="3"><input type="submit" value="Adauga in cosul de cumparaturi" name="adjQ"></td></tr></table>';
            } else {
                echo "Cart is empty";
            }
    
        }
    ?>
    </body>
    </html>