Simple PHP Shopping Cart Without Database (FREE Download)

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!

 

 

TABLE OF CONTENTS

 

PHP SHOPPING CART

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

 

 

 

PART 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 store products is to hardcode them in an array. This should be self-explanatory, the products are in the format of PRODUCT ID => [PRODUCT DETAILS].

 

PART 2) AJAX CART HANDLER

2-ajax-cart.php
<?php
if (isset($_POST["req"])) {
  // (A) INIT SHOPPING CART
  session_start();
  if (!isset($_SESSION["cartI"])) {
    $_SESSION["cartI"] = []; // cart items
    $_SESSION["cartC"] = 0;  // total quantity
  }

  // (B) UPDATE CART COUNT
  function ccount () {
    $_SESSION["cartC"] = 0;
    if (count($_SESSION["cartI"])!=0) {
      foreach ($_SESSION["cartI"] as $id=>$qty) { $_SESSION["cartC"] += $qty; }
    }
  }

  // (C) STANDARD SYSTEM RESPONSE
  function respond ($status=1, $msg="OK") {
    echo json_encode(["status"=>$status, "msg"=>$msg, "count" => $_SESSION["cartC"]]);
  }

  // (D) CART ACTIONS
  switch ($_POST["req"]) {
    // (D1) GET COUNT
    case "count": respond(); break;

    // (D2) ADD / CHANGE QUANTITY / REMOVE
    // send id only to add item
    // send id and qty to set quantity
    // send id and 0 qty to remove item
    case "set":
      $max = 99; // max allowed quantity per item
      $item = &$_SESSION["cartI"][$_POST["id"]];
      if (isset($_POST["qty"])) { $item = $_POST["qty"]; }
      else { if (isset($item)) { $item++; } else { $item = 1; } }
      if ($item<=0) { unset($_SESSION["cartI"][$_POST["id"]]); } if ($item > $max) { $item = $max; }
      ccount(); respond(); break;

    // (D3) NUKE
    case "nuke":
      $_SESSION["cartI"] = [];
      $_SESSION["cartC"] = 0;
      respond(); break;

    // (D4) GET ALL ITEMS IN CART
    case "get":
      // (D4-1) CART IS EMPTY
      if ($_SESSION["cartC"]==0) { respond(1, null); break; }

      // (D4-2) GET PRODUCTS + FILTER ILLEGAL
      require "1-products.php";
      $items = [];
      foreach ($_SESSION["cartI"] as $id=>$qty) {
        if (isset($products[$id])) {
          $items[$id] = $products[$id];
          $items[$id]["qty"] = $qty;
        } else {
          $_SESSION["cartC"] -= $_SESSION["cartI"][$id];
          unset($_SESSION["cartI"][$id]);
        }
      }
      if ($_SESSION["cartC"]==0) { respond(1, null); break; }
      respond(1, $items); break;

    // (D5) CHECKOUT
    case "checkout":
      // (D5-1) CART IS EMPTY
      if ($_SESSION["cartC"]==0) { respond(0, "Cart Empty"); break; }

      // (D5-2) EMAIL TO ADMIN
      require "1-products.php";
      $to = "admin@site.com";
      $subject = "Order Received";
      $body = "Name: " . $_POST["name"] . "\r\n";
      $body .= "Email: " . $_POST["email"] . "\r\n";
      foreach ($_SESSION["cartI"] as $id=>$qty) {
        $body .= sprintf("%s X %s\r\n", $qty, $products[$id]["name"]);
      }
      if (mail($to, $subject, $body)) {
        $_SESSION["cartI"] = [];
        $_SESSION["cartC"] = 0;
        respond();
      } else { respond(0, "ERROR SENDING MAIL"); }
      break;
  }
}

Next, we build the shopping cart, the backbone of the system. It looks intimidating, but keep calm and look closely.

  • (A) We keep the user’s shopping cart items in the PHP session.
    • $_SESSION["cartI"] An array that contains the cart items in the format of PRODUCT ID => QUANTITY.
    • $_SESSION["cartC"] The total items quantity.
  • (D) How the script work is very simple, just send the request $_POST["req"] and required parameters. For example, $_POST["req"]="set" and $_POST["id"]=1 to add product ID 1 to the cart.
Request Notes & Parameters
count Get the total items quantity.
set
  • id only – Add item to cart.
  • id and qty – Set item quantity.
  • id and qty=0 – Remove item.
nuke Remove all items.
get Get all items in cart.
checkout
  • name Customer’s name.
  • email Customer’s email.

 

 

PART 3) SHOPPING PAGE

3A) HTML SHOPPING PAGE

3a-shop.php
<!-- (A) PRODUCTS + SHOPPING CART -->
<div id="wrap">
  <!-- (A1) HEADER -->
  <div id="head">
    <div id="iCart" onclick="cart.show()">
      My Cart <span id="cCart">0</span>
    </div>
  </div>
 
  <!-- (A2) PRODUCTS -->
  <div id="products"><?php
    require "1-products.php";
    foreach ($products as $i=>$p) { ?>
    <div class="pCell">
      <img class="pImg" src="<?=$p["image"]?>">
      <div class="pName"><?=$p["name"]?></div>
      <div class="pPrice">$<?=$p["price"]?></div>
      <input class="pAdd button" type="button" value="Add To Cart" onclick="cart.add(<?=$i?>)">
    </div>
    <?php } ?>
  </div>
 
  <!-- (A3) CART ITEMS -->
  <div id="wCart">
    <span id="wCartClose" class="button" onclick="cart.toggle(cart.hWCart, false)">&#8678;</span>
    <h2>SHOPPING CART</h2>
    <div id="cart"></div>
  </div>
</div>
 
<!-- (B) CHECKOUT FORM -->
<div id="checkout"><form onsubmit="return cart.checkout()">
  <div id="coClose" class="button" onclick="cart.toggle(cart.hCO, false)">X</div>
  <label>Name</label>
  <input type="text" id="coName" required value="Jon Doe">
  <label>Email</label>
  <input type="email" id="coEmail" required value="jon@doe.com">
  <input class="button" type="submit" value="Checkout">
</form></div>

With the PHP foundations ready, we can now build the HTML page. This looks confusing once again, but the essential parts are:

  • (A2) <div id="products"> We load 1-products.php and draw the HTML products here.
  • (A3) <div id="cart"> The current shopping cart.
  • (B) <div id="checkout"> Checkout form.

 

 

3B) SHOPPING CART JAVASCRIPT

3b-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("2-ajax-cart.php", { method:"POST", body:form })
    .then(res => res.json())
    .then(res => {
      if (res.status==1) { after(res); }
      else { alert(res.msg); }
    })
    .catch(err => console.error(err));
  },
 
  // (B) HELPER - TOGGLE HTML SECTIONS
  toggle : (target, show) => {
    if (show) { target.className = "show"; }
    else { target.className = ""; }
  },
 
  // (C) INITIALIZE
  hCart : null, // html cart
  hWCart : null, // html cart wrapper
  hCCart : null, // html cart count
  hCO : null, // html checkout wrapper
  init : () => {
    // (C1) GET HTML ELEMENTS
    cart.hCart = document.getElementById("cart");
    cart.hWCart = document.getElementById("wCart");
    cart.hCCart = document.getElementById("cCart");
    cart.hCO = document.getElementById("checkout");
 
    // (C2) UPDATE CART COUNT
    cart.ajax({ req : "count" }, res => cart.count(res.count));
  },
 
  // (D) UPDATE CART COUNT
  count : qty => {
    cart.hCCart.innerHTML = qty;
    if (cart.hWCart.classList.contains("show")) { cart.show(); }
  },
 
  // (E) SHOW CART ITEMS
  show : () => {
    // (E1) RESET
    cart.toggle(cart.hWCart, true);
    cart.hCart.innerHTML = "";
 
    // (E2) LOAD & GENERATE HTML
    cart.ajax({ req : "get" }, items => {
      // (E2-1) ITEMS IN CART
      items = items.msg;
 
      // (E2-2) CART IS EMPTY
      if (items==null) {
        cart.hCart.innerHTML = `<div class="cCell empty">Cart is empty</div>`;
      }
 
      // (E2-3) DRAW CART ITEMS
      else {
        let row, subtotal, total = 0;
        for (let [id, item] of Object.entries(items)) {
          // CALCULATE SUBTOTAL
          subtotal = item["price"] * item["qty"];
          total += subtotal;
 
          // ITEM ROW
          row = document.createElement("div");
          row.className = "cCell";
          row.innerHTML = `<input class="cQty" type="number" value="${item["qty"]}" 
          min="0" max="99" onchange="cart.change(${id}, this.value)">
          <div class="cInfo">
            <div class="cName">${item["name"]}</div>
            <div class="cPrice">$${subtotal.toFixed(2)}</div>
          </div>
          <input class="cDel button" type="button" value="X" onclick="cart.remove(${id})">`;
          cart.hCart.appendChild(row);
        }
 
        // CART TOTALS
        row = document.createElement("div");
        row.className = "cCell";
        row.innerHTML = `<input class="cDel button" type="button" value="X" onclick="cart.empty()">
        <div class="cInfo">
          <div class="cName">Total</div>
          <div class="cPrice">$${total.toFixed(2)}</div>
        </div>
        <input class="cDel button" type="button" value="&gt;" onclick="cart.toggle(cart.hCO, true)">`;
        cart.hCart.appendChild(row);
      }
    });
  },
 
  // (F) ADD ITEM TO CART
  add : id => cart.ajax(
    { req : "set", id : id },
    res => cart.count(res.count)
  ),
 
  // (G) CHANGE ITEM QTY
  change : (id, qty) => cart.ajax(
    { req : "set", id : id, qty : qty },
    res => cart.count(res.count)
  ),
 
  // (H) REMOVE ITEM
  remove : id => cart.ajax(
    { req : "set", id : id, qty : 0 },
    res => cart.count(res.count)
  ),
 
  // (I) NUKE
  empty : () => { if (confirm("Reset cart?")) {
    cart.ajax(
      { req : "nuke" },
      res => cart.count(res.count)
    ); 
  }},
 
  // (J) CHECKOUT
  checkout : () => {
    cart.ajax({
      req : "checkout",
      name : document.getElementById("coName").value,
      email : document.getElementById("coEmail").value
    }, res => location.href = "3c-thank-you.html"); 
    return false;
  }
};
window.onload = cart.init;

Not going to explain line by line, so here’s a quick summary.

  • (A) ajax() A helper function to do an AJAX call to 2-ajax-cart.php.
  • (B) toggle() A helper function to toggle show/hide for the cart and checkout form.
  • (C) init() Runs on window load, pretty much just getting the HTML elements.
  • (D To J) All the cart actions.
    • count() Update the total cart quantity.
    • show() Show the cart items.
    • add() Add an item to the shopping cart.
    • change() Change item quantity.
    • remove() Remove item from cart.
    • empty() Empty the entire cart.
    • checkout() Checkout.

 

 

3C) THANK YOU PAGE

3c-thank-you.html
<h1>Thank You</h1>
<p>Order received.</p>

Lastly, a dummy “thank you” on successful order.

 

 

DOWNLOAD & NOTES

Here is the download link to the example code, so you don’t have to copy-paste everything.

 

SORRY FOR THE ADS...

But someone has to pay the bills, and sponsors are paying for it. I insist on not turning Code Boxx into a "paid scripts" business, and I don't "block people with Adblock". Every little bit of support helps.

Buy Me A Coffee Code Boxx eBooks

 

EXAMPLE CODE DOWNLOAD

Click here for the source code on GitHub gist, just click on “download zip” or do a git clone. I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

EXTRA 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 WAY BETTER SHOPPING CART

A shopping cart with product options, categories, discount coupons, user system, admin panel, API, and an installable web app - 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!

4 thoughts on “Simple PHP Shopping Cart Without Database (FREE Download)”

  1. First of all I really appreciate your work and its excellent to have the cart without database but the code above I found out that the function for Checkout not working. Could you please check and help.

    1. I check the console it stated that the syntax error in 3b-cart.js is not valid JSON mention the line fetch and catch. Im still learning as beginner I dont really have any ideas how to solve…

    2. “Invalid JSON” can be anything. Divide and conquer, get more details on what went wrong first.

       fetch("2-ajax-cart.php", { method:"POST", body:form })
      .then(res => {
        console.log(res.status);
        return res.text();
      })
      .then(txt => console.log(txt))
      .catch(err => console.error(err))

Leave a Comment

Your email address will not be published. Required fields are marked *