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:
My current problems are:
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 } ?>
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>
.