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

 

DOWNLOAD & NOTES

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

 

EXAMPLE CODE DOWNLOAD

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.

 

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

 

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" => "Lemon", "price" => 2.34, "image" => "lemon.png"],
  3 => ["name" => "Orange", "price" => 3.45, "image" => "orange.png"],
  4 => ["name" => "Avocado", "price" => 4.32, "image" => "avocado.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.

 

 

EXTRAS

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 *