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
Firstly, here is the download link to the example code as promised.
QUICK NOTES
- Open
1-products.php
, set your own products. - In
2-ajax-cart.php
, set the email to your own in the checkout section. - Launch
3a-shop.php
in the browser.
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 SHOPPING CART
All right, let us now get into the steps of building a PHP shopping cart without a database.
PART 1) PRODUCTS LIST
$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
<?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 ofPRODUCT 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 |
|
nuke |
Remove all items. |
get |
Get all items in cart. |
checkout |
|
PART 3) SHOPPING PAGE
3A) HTML SHOPPING PAGE
<!-- (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="images/<?=$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)">⇦</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 load1-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
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=">" 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 to2-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
<h1>Thank You</h1>
<p>Order received.</p>
Lastly, a dummy “thank you” on successful order.
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
- PHP MYSQL Shopping Cart – Code Boxx
- HTML Javascript Shopping Cart – Code Boxx
A BETTER SHOPPING CART

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!