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!
TABLE OF CONTENTS
PHP ECOMMERCE
All right, let us now get into more details on how the simple eCommerce website works.
PART 1) PHP LIBRARY
<?php
if (isset($_POST["req"])) {
// (A) PRODUCTS LIST
$products = [
1 => [
"n" => "Laptop",
"p" => 345.67,
"i" => "img-a.png"
],
2 => [
"n" => "Smartphone",
"p" => 123.45,
"i" => "img-b.png"
],
3 => [
"n" => "Tablet",
"p" => 234.56,
"i" => "img-c.png"
],
4 => [
"n" => "Headphones",
"p" => 34.56,
"i" => "img-d.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;
}
}
- Since there is no database, the only way is to hardcode products in an array. This is in the structure of
ID => DETAILS
.n
Product name.p
Product price.i
Product image.
- 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 ofID : QUANTITY
.$_POST["ANY OTHER"]
Other information such as name, email, telephone, address, whatever you want to capture.
PART 2) SHOPPING PAGE
<!-- (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')">⇦</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>
- 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.
- A hidden checkout form. Feel free to add more fields that you want to capture.
PART 3) THE JAVASCRIPT
3A) AJAX FETCH HELPER FUNCTION
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 to1-lib.php
.
3B) PROPERTIES
// (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 from1-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
// (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="pDetails">
<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})">
</div>`;
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 fromlocalStorage
toshop.cart
. - (C4) Fetch the product entries from
1-lib.php
, and draw the HTML products plus cart items.
3D) CART ACTIONS
// (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=">" 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()
Savesshop.cart
into thelocalStorage
. - (E)
drawcart()
Loops through the current cart itemsshop.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.
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.
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
- Arrow Functions – CanIUse
- Fetch – CanIUse
- Local Storage – CanIUse
This example should work on all modern “Grade A” browsers.
A WAY BETTER SHOPPING CART

LINKS & REFERENCES
- PHP Send Email With HTML Template – Code Boxx
- Shopping Cart With PHP MySQL – Code Boxx
- Simple User Registration With PHP MYSQL – Code Boxx
- Simple User Login With PHP MYSQL – Code Boxx
- User Role Management With PHP MYSQL – Code Boxx
- Very Simple Pure HTML CSS Admin Panel – Code Boxx
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!