Simple Step-By-Step PHP Shopping Cart (Without Database)

Welcome to a tutorial on how to create a simple PHP shopping cart. Without a database, that is. Need a simple “no database cart”? Well, it is possible, but it is still not a straightforward thing. So let us walk through an example, read on!

ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

 

 

TABLE OF CONTENTS

Download & Notes Shopping Cart Useful Bits & Links
The End

 

DOWNLOAD & NOTES

Firstly, here is the download link to the example code as promised.

 

QUICK NOTES

If you just want to “quick start” and trace on your own:

  • Open 1-products.php, set your own products.
  • Set the email in 6-checkout.php to your own.
  • Launch 2-shop.php in the browser.
If you spot a bug, feel free to comment below. I try to answer short questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.

 

 

EXAMPLE CODE DOWNLOAD

Click here to download all the example source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

 

PHP SHOPPING CART

All right, let us now get into the steps of building a PHP shopping cart.

 

STEP 1) PRODUCTS LIST

1-products.php
$products = [
  1 => ["name" => "Apple", "price" => 1.23, "image" => "apple.png"],
  2 => ["name" => "Mango", "price" => 2.34, "image" => "mango.png"],
  3 => ["name" => "Orange", "price" => 3.45, "image" => "orange.png"],
  4 => ["name" => "Pear", "price" => 4.32, "image" => "pear.png"]
];

Since we don’t have a database, the only way is to hardcode the products… This should be self-explanatory, just a plain old array PRODUCT ID => [PRODUCT DETAILS]. Add your own product description if you want.

 

STEP 2) SHOP PAGE

2-shop.php
<!-- (A) AVAILABLE PRODUCTS -->
<div id="products"><?php
  require "1-products.php";
  foreach ($products as $pid=>$p) { ?>
  <div class="pCell">
    <div class="pTxt">
      <div class="pName"><?=$p["name"]?></div>
      <div class="pPrice">$<?=$p["price"]?></div>
    </div>
    <img class="pImg" src="images/<?=$p["image"]?>"/>
    <button class="pAdd" onclick="cart.add(<?=$pid?>)">
      Add To Cart
    </button>
  </div>
<?php } ?></div>
 
<!-- (B) CART -->
<div id="cart"></div>

Next, we simply loop through the products array to build a “nice HTML products page”. Take note of onclick="cart.add(PRODUCT ID)" here, we will deal with all the cart actions in the next step.

 

 

STEP 3) AJAX CART HANDLER

3-ajax-cart.php
// (A) INIT SHOPPING CART SESSION
session_start();
if (!isset($_SESSION["cart"])) { $_SESSION["cart"] = []; }
 
// (B) STANDARD RESPONSE
function respond ($status=1, $msg="") {
  exit(json_encode(["status"=>$status, "msg"=>$msg]));
}
 
if (isset($_POST["req"])) { switch ($_POST["req"]) {
  // (C) INVALID
  default: respond(0, "Invalid Request");
 
  // (D) ADD TO CART
  case "add":
    $qty = &$_SESSION["cart"][$_POST["pid"]];
    if (isset($qty)) { $qty++; } else { $qty = 1; }
    if ($qty > 99) { $qty = 99; }
    respond();
 
  // (E) CHANGE QUANTITY
  case "set":
    $qty = &$_SESSION["cart"][$_POST["pid"]];
    $qty = $_POST["qty"];
    if ($qty > 99) { $qty = 99; }
    if ($qty <= 0) { unset($_SESSION["cart"][$_POST["pid"]]); }
    respond();
 
  // (F) REMOVE ITEM
  case "del":
    unset($_SESSION["cart"][$_POST["pid"]]);
    respond();
 
  // (G) NUKE
  case "nuke":
    $_SESSION["cart"] = [];
    respond();
 
  // (H) GET ALL ITEMS IN CART
  case "get":
    // (H1) EMPTY CART
    if (count($_SESSION["cart"])==0) { respond(1, null); }
 
    // (H2) FILTER ILLEGAL PRODUCTS
    require "1-products.php";
    $items = [];
    foreach ($_SESSION["cart"] as $pid=>$qty) {
      if (isset($products[$pid])) {
        $items[$pid] = $products[$pid];
        $items[$pid]["qty"] = $qty;
      } else { unset($_SESSION["cart"][$pid]); }
    }
    if (count($_SESSION["cart"])==0) { respond(1, null); }
 
    // (H3) RESPOND
    respond(1, $items);
}}

Right, this part looks intimidating, but how it works is simple.

  • We send a $_POST["req"] to this script, followed by the required parameters to perform a cart action. For example, $_POST = ["req"=>"set", "pid"=>1, "qty"=>11] will set 11 apples in the cart.
  • The shopping cart is stored in $_SESSION["cart"], in the format of PRODUCT ID => QUANTITY.

 

Request Description & Parameters
add Add an item to the cart.

  • pid The product ID.
set Set the item quantity.

  • pid The product ID.
  • qty Quantity to set.
del Remove an item from the cart.

  • pid The product ID.
nuke Clear the entire cart.
get Get the contents and details of the current shopping cart.

 

 

STEP 4) SHOPPING CART JAVASCRIPT

4-cart.js
var cart = {
  // (A) HELPER - AJAX FETCH
  ajax : (data, after) => {
    // (A1) FORM DATA
    let form = new FormData();
    for (let [k, v] of Object.entries(data)) { form.append(k, v); }

    // (A2) FETCH
    fetch("3-ajax-cart.php", { method:"POST", body:form })
    .then((res) => res.json()).then((res) => {
      if (res.status!=1) { alert(res.msg); }
      else if (after) { after(res.msg); }
    }).catch((err) => {
      alert("Error");
      console.error(err);
    });
  },

  // (B) SHOW ITEMS IN CART
  show : () => {
    cart.ajax({ req : "get" }, (items) => {
      // (B1) GET HTML CART
      let hcart = document.getElementById("cart");
      hcart.innerHTML = "";

      // (B2) EMPTY CART
      if (items===null) { hcart.innerHTML = "Cart is empty."; }

      // (B3) DRAW CART ITEMS
      else {
        let total = 0;
        for (let [id, pdt] of Object.entries(items)) {
          // ITEM ROW HTML ELEMENTS
          let row = document.createElement("div"),
              rowA = document.createElement("button"),
              rowB = document.createElement("div"),
              rowC = document.createElement("input");

          // DELETE BUTTON
          rowA.innerHTML = "X";
          rowA.onclick = () => { cart.del(id); };
          rowA.className = "cDel";
          row.appendChild(rowA);

          // NAME
          rowB.innerHTML = pdt.name;
          rowB.className = "cName";
          row.appendChild(rowB);

          // QUANTITY
          rowC.type = "number";
          rowC.value = pdt.qty;
          rowC.min = 0; rowC.max = 99;
          rowC.onchange = function () { cart.set(id, this.value); };
          rowC.className = "cQty";
          row.appendChild(rowC);

          // ADD TO GRAND TOTAL
          total += pdt.qty * pdt.price;

          // ENTIRE ROW
          row.className = "cRow";
          hcart.appendChild(row);
        }

        // GRAND TOTAL
        let row = document.createElement("div");
        row.innerHTML = "TOTAL $" + total.toFixed(2);
        row.className = "cTotal";
        hcart.appendChild(row);

        // CHECKOUT
        row = document.createElement("button");
        row.innerHTML = "Checkout";
        row.className = "cOut";
        row.onclick = () => { location.href = "5-order.php"; };
        hcart.appendChild(row);

        // EMPTY CART
        row = document.createElement("button");
        row.innerHTML = "Empty";
        row.className = "cNuke";
        row.onclick = cart.nuke;
        hcart.appendChild(row);
      }
    });
  },

  // (C) ADD ITEM TO CART
  add : (pid) => {
    cart.ajax({ req : "add", pid : pid }, cart.show);
  },

  // (D) CHANGE QUANTITY
  set : (pid, qty) => {
    cart.ajax({ req : "set", pid : pid, qty : qty }, cart.show);
  },

  // (E) REMOVE ITEM
  del : (pid) => {
    cart.ajax({ req : "del", pid : pid }, cart.show);
  },

  // (F) NUKE
  nuke : () => { if (confirm("Empty cart?")) {
    cart.ajax({ req : "nuke" }, cart.show);
  }}
};
window.addEventListener("DOMContentLoaded", cart.show);

Again, we have another seemingly difficult script. Keep calm and look carefully.

  • (A) ajax() A helper function to do an AJAX call to the previous 3-ajax-cart.php.
  • (B) show() Get the contents of the cart, draw the HTML.
  • (C To F) All the cart actions.
    • add() Add an item to the cart, update the HTML.
    • set() Change the quantity of an item, update the HTML.
    • del() Remove an item, update the HTML.
    • nuke() Empty the cart, update the HTML.

Easy?

 

 

STEP 5) ORDER PAGE

5-order.php
<form method="post" action="6-checkout.php" id="order">
  <label for"name">Name</label>
  <input type="text" name="name" required/>
  <label for"name">Email</label>
  <input type="email" name="email" required/>
  <input type="submit" value="Place Order"/>
</form>

Next, we have a simple order form when the user clicks on “checkout”. Because there is no database, the only way is to capture the user details and send them out via email.

 

STEP 6) CHECKOUT

6-checkout.php
// (A) CHECKS
session_start();
if (!isset($_SESSION["cart"]) || count($_SESSION["cart"])==0) {
  exit("Cart is empty");
}
if (!isset($_POST["name"]) || !isset($_POST["email"])) {
  exit("Invalid request");
}
 
// (B) SEND EMAIL - CHANGE TO YOUR OWN!
$to = "admin@site.com";
$subject = "Order Received";
$body = "";
require "1-products.php";
foreach ($_SESSION["cart"] as $pid=>$qty) {
  $body .= sprintf("%s X %s\r\n", $qty, $products[$pid]["name"]);
}
if (mail($to, $subject, $body)) {
  echo "OK";
  $_SESSION["cart"] = [];
} else { echo "ERROR"; }

Finally, this should be self-explanatory again – We simply collect the form data and cart items into an email.

 

 

USEFUL BITS & LINKS

That’s all for the tutorial, and here is a small section on some extras and links that may be useful to you.

 

LINKS & REFERENCES

 

A BETTER SHOPPING CART

Need a shopping cart with product options? Product categories? Discount coupons? User system and admin panel? Click here to check out my eBook!

 

THE END

Thank you for reading, and we have come to the end. I hope that it has helped you to better understand, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!

Leave a Comment

Your email address will not be published.