Simple eCommerce Website With PHP (No Database)

Welcome to a tutorial on how to create a simple eCommerce website with PHP. Want to build an eCommerce website? Only to find overly complex project examples all over the Internet? Well, here’s a simple one that does not involve a database – 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

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

 

QUICK NOTES

  • Access 2-shop.html in the browser, Captain Obvious to the rescue – Use http:// not file://.
  • Set your own products in 1-lib.php.
  • Complete your own checkout sequence in 1-lib.php and 3-shop.js.
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.

 

SCREENSHOT

 

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 ECOMMERCE

All right, let us now get into more details on how the simple eCommerce website works.

 

PART 1) PHP LIBRARY

1-lib.php
<?php
if (isset($_POST["req"])) {
  // (A) PRODUCTS LIST
  $products = [
    1 => [
      "n" => "Laptop",
      "p" => 345.67,
      "i" => "laptop.png"
    ],
    2 => [
      "n" => "Tablet",
      "p" => 234.56,
      "i" => "tablet.png"
    ],
    3 => [
      "n" => "Smartphone",
      "p" => 123.45,
      "i" => "smartphone.png"
    ],
    4 => [
      "n" => "Router",
      "p" => 34.56,
      "i" => "router.png"
    ],
    5 => [
      "n" => "Keyboard",
      "p" => 23.45,
      "i" => "keyboard.png"
    ],
    6 => [
      "n" => "Mouse",
      "p" => 12.34,
      "i" => "mouse.png"
    ]
  ];

  // (B) HANDLE REQUESTS
  switch ($_POST["req"]) {
    // (B1) INVALID REQUEST
    default: echo "Invalid request"; break;
  
    // (B2) GET PRODUCTS
    case "get":
      echo json_encode($products);
      break;

    // (B3) CHECKOUT
    case "checkout":
      // (B3-1) DATA YOGA
      $cart = json_decode($_POST["cart"], true);
      unset($_POST["req"]);
      unset($_POST["cart"]);

      // (B3-2) SEND VIA EMAIL
      $msg = "";
      foreach ($_POST as $k=>$v) { $msg .= "$k : $v\r\n"; }
      foreach ($cart as $i=>$q) {
        $msg .= sprintf("%u X %s - $%s\r\n",
          $q, $products[$i]["n"], $q * $products[$i]["p"]
        );
      }
      echo mail("admin@site.com", "Order Received", $msg)
        ? "OK" : "Failed to send email";
      break;
  }
}
  1. Since there is no database, the only way is to hard code products in an array. This is in the structure of ID => DETAILS.
    • n Product name.
    • p Product price.
    • i Product image.
  2. This part is the AJAX handler, just send the request $_POST["req"] along with the required parameters.
    • $_POST["req"] = "get" Outputs the list of products in a JSON encoded string.
    • $_POST["req"] = "checkout" Checks out the cart items, and sends them out via email. Remember to change the email address to your own.
      • $_POST["cart"] Required. A JSON encoded string of cart items, in the format of ID : QUANTITY.
      • $_POST["ANY OTHER"] Other information such as name, email, telephone, address, whatever you want to capture.

 

 

PART 2) SHOPPING PAGE

2-shop.html
<!-- (A) PRODUCTS + SHOPPING CART -->
<div id="wrap">
  <!-- (A1) HEADER -->
  <div id="head">
    <div id="iCart">
      My Cart <span id="cCart">0</span>
    </div>
    <div id="iDummy">My Account</div>
  </div>
 
  <!-- (A2) PRODUCTS -->
  <div id="products"></div>
 
  <!-- (A3) CART ITEMS -->
  <div id="wCart">
    <span id="wCartClose" class="button" onclick="document.getElementById('wCart').classList.remove('show')">&#8678;</span>
    <h2>SHOPPING CART</h2>
    <div id="cart"></div>
  </div>
</div>
 
<!-- (B) CHECKOUT FORM -->
<div id="checkout"><form onsubmit="return shop.checkout()">
  <div id="cgClose" class="button" onclick="shop.togcf(false)">X</div>
  <label>Name</label>
  <input type="text" name="name" required value="Jon Doe">
  <label>Email</label>
  <input type="email" name="email" required value="jon@doe.com">
  <input class="button" type="submit" value="Checkout">
</form></div>
  1. The “main page” itself.
    • <div id="head"> Pretty much just a “toggle show/hide cart” button.
    • <div id="products"> A container to draw the products in.
    • <div id="cart"> To draw the current cart items.
  2. A hidden checkout form. Feel free to add more fields that you want to capture.

 

PART 3) THE JAVASCRIPT

3A) AJAX FETCH HELPER FUNCTION

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

    // (A2) FETCH
    fetch("1-lib.php", { method : "post", body : form })
    .then(res => res.text())
    .then(txt => after(txt))
    .catch(err => console.error(err));
  },
  // ...
};
  • var shop is an object that contains all the “shopping” mechanisms.
  • shop.fetch() is but a simple helper function to do an AJAX call to 1-lib.php.

 

 

3B) PROPERTIES

3-shop.js
// (B) PROPERTIES
hPdt : null, // html products
hCart : null, // html cart
hCCart : null, // html cart count
hCO : null, // html checkout wrapper
hCOF : null, // html checkout form
products : null, // products list
cart : null, // cart items
qty : 0, // cart total item quantity
total : 0, // cart total amount
  • hPdt hCart hCCart hCO hCOF References to HTML elements.
  • products Array of products, which will be loaded from 1-lib.php.
  • cart The current cart items, in the structure of { ID : QUANTITY }.
  • qty The current total quantity.
  • total The current total amount.

 

3C) INITIALIZE

3-shop.js
// (C) INITIALIZE
init : () => {
  // (C1) GET HTML ELEMENTS
  shop.hPdt = document.getElementById("products");
  shop.hCart = document.getElementById("cart");
  shop.hCCart = document.getElementById("cCart");
  shop.hCO = document.getElementById("checkout");
  shop.hCOF = document.querySelector("#checkout form");
 
  // (C2) CLICK TO TOGGLE CART
  document.getElementById("iCart").onclick = () => {
    document.getElementById("wCart").classList.toggle("show");
  };
 
  // (C3) RESTORE CART
  shop.cart = localStorage.getItem("cart");
  if (shop.cart == null) { shop.cart = {}; }
  else { shop.cart = JSON.parse(shop.cart); }
 
  // (C4) LOAD PRODUCTS > DRAW HTML
  shop.fetch({"req": "get"}, data => {
    // (C4-1) PARSE DATA INTO JS OBJECT
    shop.products = JSON.parse(data);
 
    // (C4-2) DRAW HTML PRODUCTS
    for (let [id, pdt] of Object.entries(shop.products)) {
      let row = document.createElement("div");
      row.className = "pCell";
      row.innerHTML = `<img class="pImg" src="assets/${pdt.i}">
      <div class="pName">${pdt.n}</div>
      <div class="pPrice">$${pdt.p.toFixed(2)}</div>
      <input class="pAdd button" type="button" value="Add To Cart" onclick="shop.add(${id})">`;
      shop.hPdt.appendChild(row);
    }
 
    // (C4-3) DRAW CART ITEMS
    shop.drawcart();
  });
},
window.onload = shop.init;

shop.init() Runs on page load. Not going to explain line-by-line, but a quick walkthrough:

  • (C1) Get all the related HTML elements.
  • (C2) Click to toggle show/hide the cart items.
  • (C3) The shopping cart is saved in the localStorage as a JSON encoded string. This part simply restores the cart session from localStorage to shop.cart.
  • (C4) Fetch the product entries from 1-lib.php, and draw the HTML products plus cart items.

 

 

3D) CART ACTIONS

3-shop.js
// (D) SAVE CART ITEMS INTO LOCALSTORAGE
save : () => {
  localStorage.setItem("cart", JSON.stringify(shop.cart));
},
 
// (E) DRAW CART ITEMS
drawcart : () => {
  // (E1) RESET
  let row;
  shop.total = 0;
  shop.hCart.innerHTML = "";
 
  // (E2) EMPTY CART
  if (Object.keys(shop.cart).length==0) {
    row = document.createElement("div");
    row.className = "cCell";
    row.innerHTML = `Cart is empty`;
    shop.hCart.appendChild(row);
    shop.hCCart.innerHTML = 0;
  }
 
  // (E3) DRAW ITEMS
  else {
    for (let [i, q] of Object.entries(shop.cart)) {
      // (E3-1) CALCULATE SUBTOTAL
      let subtotal = q * shop.products[i]["p"];
      shop.total += subtotal;
      shop.qty += parseInt(q);
 
      // (E3-2) ITEM ROW
      row = document.createElement("div");
      row.className = "cCell";
      row.innerHTML = `<input class="cQty" type="number" value="${q}" 
      min="0" max="99" onchange="shop.change(${i}, this.value)">
      <div class="cInfo">
      <div class="cName">${shop.products[i]["n"]}</div>
      <div class="cPrice">$${subtotal.toFixed(2)}</div>
      </div>
      <input class="cDel button" type="button" value="X" onclick="shop.remove(${i})">`;
      shop.hCart.appendChild(row);
    }
 
    // (E3-3) CART TOTAL
    row = document.createElement("div");
    row.className = "cCell";
    row.innerHTML = `<input class="cDel button" type="button" value="X" onclick="shop.empty()">
    <div class="cInfo">
    <div class="cName">Total</div>
    <div class="cPrice">$${shop.total.toFixed(2)}</div>
    </div>
    <input class="cDel button" type="button" value="&gt;" onclick="shop.togcf(true)">`;
    shop.hCart.appendChild(row);
 
    // (E3-4) TOTAL QUANTITY
    shop.hCCart.innerHTML = shop.qty;
  }
},
 
// (F) ADD PRODUCT TO CART
add : id => {
  if (shop.cart[id]==undefined) { shop.cart[id] = 1; }
  else { shop.cart[id]++; }
  shop.save(); shop.drawcart();
},

// (G) CHANGE QUANTITY IN CART
change : (id, qty) => {
  if (qty <= 0) { shop.remove(id) }
  else { shop.cart[id] = qty; }
  shop.save(); shop.drawcart();
},
 
// (H) REMOVE PRODUCT FROM CART
remove : id => {
  delete shop.cart[id];
  shop.save(); shop.drawcart();
},
 
// (I) EMPTY CART
empty : () => { if (confirm("Empty cart?")) {
  shop.cart = {};
  shop.save(); shop.drawcart();
}},
 
// (J) TOGGLE CHECKOUT FORM
togcf : show => {
  if (show) { shop.hCO.className = "show"; }
  else { shop.hCO.className = ""; }
},
 
// (K) CHECKOUT
checkout : () => {
  // (K1) FORM DATA
  let form = new FormData(shop.hCOF);
  form.append("req", "checkout");
  form.append("cart", JSON.stringify(shop.cart));
 
  // (K2) AJAX PROCESS
  shop.fetch(form, res => {
    if (res=="OK") {
      shop.cart = {};
      shop.save();
      shop.drawcart();
      shop.togcf(false);
      alert("CHECKOUT OK. DO SOMETHING - REDIRECT TO THANK YOU?");
    } else { alert(res); }
  });

  // (K3) PREVENT FORM SUBMIT
  return false;
}

The last few sections of the Javascript deal with the shopping cart.

  • (D) save() Saves shop.cart into the localStorage.
  • (E) drawcart() Loops through the current cart items shop.cart and draws the HTML.
  • (F) add() Add an item to the cart.
  • (G) change() Update item quantity.
  • (H) remove() Remove item from the cart.
  • (I) empty() Remove all items from the cart.
  • (J) togcf() Show/hide the checkout form.
  • (K) checkout() Checkout the current cart items. Complete this function on your own.

 

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.

 

IMPROVEMENT IDEAS

This example works, but it is extremely simplistic. A lot can be done to make it better.

  • Complete the checkout process – Capture more fields, send to admin, send to customer, and create your own “nice email template”. See links below.
  • Add more security and checks – Double-check the checkout in 1-lib.php for valid name/email/products.
  • If you want user registration and login, the only way is to involve a database. Keeping user data in a flat file is never a good idea. See links below.
  • Admin Panel – It is possible to build a simple one and secure it using HTTP authentication.
  • Online payment – Paypal, Stripe, Google Pay, Apple Pay, Wise, Payoneer, whatever else.

The possibilities are endless and I cannot give free consultations to everyone. The rest is up to you to complete.

 

 

COMPATIBILITY CHECKS

This example should work on all modern “Grade A” browsers.

 

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!

 

LINKS & REFERENCES

 

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.