Search code examples
phphtmlsession-variablesshopping-cart

Shopping cart using PHP $_Session


I'm learning PHP and I'm trying to create a shopping cart using only PHP and $_SESSION

What I'm trying to achieve is:

  • Adding an existing product only updates a quantity variable
  • A delete button that decreases a quantity variable and then removes the item from the cart when quantity = 0
  • A clear cart button which removes everything from the cart

My current problems are:

  • Products can be added multiple times but the item keeps reappearing in the cart and the quantity isn't updated.
  • Neither the delete button nor clear cart button is currently working.

I'm struggling with implementing a global quantity variable, I don't understand how to manage it and update it.

I feel like I'm being a bit hopeful/naive with my delete function and that the array check is off, but I'm unsure how to fix it.

I think that the reset cart function is close, but I'm short one step. I just don't know where

Any help would be or a nudge in the right direction would be appreciated, thanks in advance.

My code

<?php
session_start ();

$items = [
[ "name" => "Lord of the Rings", "price" => 16.72 ],
[ "name" => "The Name of The Wind", "price" => 35.54 ],
[ "name" => "The Way of Kings", "price" => 32.237 ],
[ "name" => "Gravity Rising", "price" => 24.75 ],
[ "name" => "The Hobbit", "price" => 30.30 ],
]; 

//loads cart
if (! isset ( $_SESSION ['cart'] )) {
    $_SESSION ['cart'] = array ();
    
       //Attempt to add quantity variabke for cart
       // for ($i = 0; $i < count($products); $i++) {
       // $_SESSION["qty"][$i] = 0;
       //}
}

// Add
if (isset ( $_POST ["buy"] )) {
     
    //Atempt to add quantity variable 
    //If item is already in cart, quantity += 1. Else add item.
    //if (in_array($_POST ["buy"], $_SESSION['cart'])) {
       $_SESSION ['cart'][] = $_POST["buy"];
       
        
    //}
}

// Delete Item
else if (isset ( $_POST ['delete'] )) { 
    if (false !== $key = array_search($_POST['delete'], $_SESSION['cart'])) { // check item in array
    unset($_SESSION['cart'][$key]); // remove item
    }


    
}

// Empty Cart
else if (isset ( $_POST ["reset"] )) { // remove item from cart
    unset ( $_SESSION ['cart'] );
}

?>

<form action='<?php echo $_SERVER['PHP_SELF']; ?>' method='post'>
  <form action='<?php echo $_SERVER['PHP_SELF']; ?>' method='post'>
    <?php
        foreach ( $items as $ino => $item ) {
            $name = $item ['name'];

            $price = $item ['price'];

            echo " <p>$name</p>";
            echo '<p>$' . number_format((float)$item['price'], 2, '.', '') . '</p>';

            
            echo "<button type='submit' name='buy' value='$ino'>Buy</button> ";
        }

            
        
    ?>
</form>


<?php
if (isset ( $_SESSION ["cart"] )) {
    ?>

<form action='(omitted link)'
target='_blank' method='post'
enctype='application/x-www-form-urlencoded'>
<table>
    <tr>
        <th>Product</th>
        <th>Price</th>
        <th>Quantity</th>
        <th>Action</th>
    </tr>
   <?php
// Set a default total
$total = 0;
foreach ( $_SESSION['cart'] as $ino ) {
    ?>
<tr>
    <td>
        <?php echo $items[$ino]['name']; ?>
    </td>
    <td>
        <?php echo  number_format((float)$items[$ino]['price'], 2, '.', ''); ?>
    </td>
    <td>
        Quantity: <?php echo "";?>        
    </td>
    <td>
        <button type='submit' name='reset' value='<?php echo $ino;    ?>'>Delete</button>
    </td>
</tr>
<?php
    $total += number_format((float)$items[$ino]['price'], 2, '.', '');
} // end foreach
?>

Total: $<?php echo $total; ?>
    <tr>
        <td colspan="2">Total: $<?php echo($total); ?></td>
        
    </tr>
    <tr>
        <td><button type='submit' name='clear'>Clear cart</button></td>
    </tr>
</table>
</form>
<?php  } ?>

Solution

  • Welcome to Stack Overflow!

    There is one major issue with your code:

    foreach loop and assignment:

    foreach ( $items as $ino => $item ) { in combination with echo "<button type='submit' name='buy' value='$ino'>Buy</button> "; is dangerous. $ino refers to the array index, in the moment a new product is added somewhere in the list (and not at the end of it) all elements in the cart might point to the wrong product.

    Example:

    You have an array with ['Apple', 'Orange', 'Banana']. User decides to add all three to the cart. The cart now contains [0, 1, 2] or "Apple, Orange, Banana".

    If these values would now come from a database, someone might have added "Strawberry" to the list and reordered the catalog so the new array would be something like ['Apple', 'Strawberry', 'Orange', 'Banana']. The cart would still have the old values [0, 1, 2] and would now point to "Apple, Strawberry, Orange". Instead use a product ID right from the start.

    Fix and a bit of help:

    I am not going to write your code as you want to learn it yourself. But just to give you some advice and help here are some hints.

    Use a product ID:

    $items = [
    [ "pid" => "LOTR", "name" => "Lord of the Rings", "price" => 16.72 ],
    [ "pid" => "NameWind", "name" => "The Name of The Wind", "price" => 35.54 ],
    [ "pid" => "WayKings", "name" => "The Way of Kings", "price" => 32.237 ],
    [ "pid" => "GravRi", "name" => "Gravity Rising", "price" => 24.75 ],
    [ "pid" => "Hobbit", "name" => "The Hobbit", "price" => 30.30 ],
    ]; 
    

    Use the key in the cart session variable:

    In the loop use the ID as product reference:

    $pid = $item ['pid'];
    echo "<button type='submit' name='buy' value='$pid'>Buy</button> ";
    

    ... and increment the value by one if it is already in the cart ...

    if (isset ( $_POST["buy"] )) {
        if (array_key_exists($_POST["buy"], $_SESSION['cart'])) {
          $_SESSION['cart'][$_POST["buy"]] += 1;
        } else {
          $_SESSION['cart'][$_POST["buy"]] = 1;
        }
    }
    

    Then decrement the value using the same approach for the delete button.

    Resetting the cart:

    The cart won't get cleared as you are checking for $_POST["reset"] but the button has the name "clear": <button type='submit' name='clear'>Clear cart</button>.