Ben
Ben

Reputation: 305

Create a one page shopping cart using PHP $_Session and NO SQL

I am learning some PHP and I am trying to create a all in one page shopping cart.

I have read into and can see the benefits of a SQL bases system, but I want to learn the basics first. In doing so I have create a all-in-one page that contains the products in an associated array, as well as a form that submits to itself.

What I want to achieve is:

My current problem is:

Again, I am not looking for a SQL solution yet, just a pure PHP using $_SESSION and $_POST and would like to use buttons instead of <a href add?> type links.

Thanks for the lengthy read in advance here is the code:

<?php
session_start ();

$items = array (
        'A123' => array (
                'name' => 'Item1',
                'desc' => 'Item 1 description...',
                'price' => 1000 
        ),
        'B456' => array (
                'name' => 'Item40',
                'desc' => 'Item40 description...',
                'price' => 2500 
        ),
        'Z999' => array (
                'name' => 'Item999',
                'desc' => 'Item999 description...',
                'price' => 9999 
        ) 
);

if (! isset ( $_SESSION ['cart'] )) {
    $_SESSION ['cart'] = array ();
}

// Add
if (isset ( $_POST ["buy"] )) {
    $_SESSION ['cart'] = $_POST;
} 

// Delete Item
else if (isset ( $_POST ['delete'] )) { // a remove button has been clicked
    unset ( $_POST ['delete'] ); //
} 

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

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

            echo " <p>$title</p>";
            echo " <p>$desc</p>";
            echo "<p>\$$price</p>";

            if ($_SESSION ['cart'] == $ino) {
                echo '<img src="carticon.png">';
                echo "<p><button type='submit' name='delete' value='$ino'>Remove</button></p>";
            } else {
                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>Action</th>
    </tr>
    <?php

    $total = 0;
    foreach ( $_SESSION ["cart"] as $i ) {
        ?>
    <tr>
        <td>
            <?php echo($_SESSION["cart"]); ?> <!--Item name-->
        </td>
        <td>price<?php echo($_SESSION["price"][$i] ); ?>
            <!--Item cost-->
        </td>
        <td><button type='submit' name='delete' value='$ino'>Remove</button>
            </p></td>
    </tr>
    <?php
        $total = + $_SESSION ["amounts"] [$i];
    }
    $_SESSION ["total"] = $total;
    ?>
    <tr>
        <td colspan="2">Total: $<?php echo($total); ?></td>
        <td><input type='submit' value='Checkout' /></td>
    </tr>
    <tr>
        <td><button type='submit' name='clear'>Clear cart</button></td>
    </tr>
</table>
</form>
<?php  } ?>

Upvotes: 1

Views: 5377

Answers (1)

Kirk Beard
Kirk Beard

Reputation: 9843

There's a few things that need fixing in your script, so I'll break them down into their individual parts.

There's a lot of security error checks that should also be done with the code, but as a pure learning exercise, I'm bypassing those factors.

Defining the cart

You're defining the shopping cart as an array:

if (! isset ( $_SESSION ['cart'] )) {
    $_SESSION ['cart'] = array ();
}

However, when you add an item to the cart, you're replacing the cart:

// Add
if (isset ( $_POST ["buy"] )) {
    $_SESSION ['cart'] = $_POST; // 
} 

To add an item to the cart, you should be using $cart[] = $_POST, but, there are additional things to take into account.

Adding to cart

The $cart[] = $_POST adds the full $_POST data to the cart, when you only need the product ID. The correct way would be:

// Add
if (isset ( $_POST ["buy"] )) {
    // Check the item is not already in the cart
    if (!in_array($_POST ["buy"], $_SESSION['cart'])) {
        // Add new item to cart
        $_SESSION ['cart'][] = $_POST["buy"];
    }
}

This would result in the cart storing multiple values. For example, a print_r($_SESSION['cart']) might show:

array (
    0 => 'A123',
    1 => 'B456'
);

Each item in this array would be an item that has been added to your cart.

Removing an item from your cart

Now that the structure of $_SESSION['cart'] has been changed, the "remove from cart" action requires updates too. Using a little snippet of code, we can check if the value exists in the array, find its key, and remove it.

// Delete Item
else if (isset ( $_POST ['delete'] )) { // a remove button has been clicked
    // Remove the item from the cart
    if (false !== $key = array_search($_POST['delete'], $_SESSION['cart'])) {
        unset($_SESSION['cart'][$key]);
    }
}

Check if the item is in your cart

Further changes to your code would be required to support the new array structure. You can use in_array to check if your product is contained in the cart array.

<?php
    foreach ( $items as $ino => $item ) {
        // ... snipped for brevity

        // Check if an item is in the cart by checking for the existence of its ID:
        if (in_array($ino, $_SESSION['cart'])) { // The $ino would be 'a123' for your first product
            echo "<p><button type='submit' name='delete' value='$ino'>Remove</button></p>";
        } else {
            echo "<button type='submit' name='buy' value='$ino'>Buy</button> ";
        }
    }
?>

Simplifying your code

In the above code, I've removed some of the code. You are doing the following:

$title = $item ['name'];
$desc = $item ['desc'];
$price = $item ['price'];

echo " <p>$title</p>";
echo " <p>$desc</p>";
echo "<p>\$$price</p>";

This can be simplified to:

echo "<p>$item['name']</p>";
echo "<p>$item['desc']</p>";
echo "<p>\$$item['price']</p>";

Rather than the double $$ in the last line, I personally would use:

echo '<p>$' . number_format($item['name']) . '</p>';

This allows you to format the display of the number easier. Alternatively, you could use money_format.

Displaying the shopping cart

There are a few problems with this code.

  1. You're attempting to echo($_SESSION['cart']) which won't work. You cannot echo an array
  2. You're using foreach ($_SESSION ["cart"] as $i) incorrectly when attempting to display the values using <?php echo($_SESSION["price"][$i] ); ?>
  3. You're complicating the code used for the $total value
  4. The HTML isn't valid due to a random </p> thrown into the mix

The correct way to display this would be:

<?php
// Set a default total
$total = 0;
foreach ( $_SESSION['cart'] as $ino ) {
    ?>
<tr>
    <td>
        Name: <?php echo $items[$ino]['name']; ?>
    </td>
    <td>
        Price: <?php echo $items[$ino]["price"]; ?>
    </td>
    <td>
        <button type='submit' name='delete' value='<?php echo $ino; ?>'>Remove</button>
    </td>
</tr>
<?php
    $total += $items[$ino]['price'];
} // end foreach
?>

Total: $<?php echo $total; ?>

Upvotes: 3

Related Questions