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
If you just want to “quick start” and trace on your own:
- Open
1-products.php
, set your own products. - Set the email in
6-checkout.php
to your own. - Launch
2-shop.php
in the browser.
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.
STEP 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 to hardcode the products… This should be self-explanatory, just a plain old array PRODUCT ID => [PRODUCT DETAILS]
. Add your own product description if you want.
STEP 2) SHOP PAGE
<!-- (A) AVAILABLE PRODUCTS -->
<div id="products"><?php
require "1-products.php";
foreach ($products as $pid=>$p) { ?>
<div class="pCell">
<div class="pTxt">
<div class="pName"><?=$p["name"]?></div>
<div class="pPrice">$<?=$p["price"]?></div>
</div>
<img class="pImg" src="images/<?=$p["image"]?>"/>
<button class="pAdd" onclick="cart.add(<?=$pid?>)">
Add To Cart
</button>
</div>
<?php } ?></div>
<!-- (B) CART -->
<div id="cart"></div>
Next, we simply loop through the products array to build a “nice HTML products page”. Take note of onclick="cart.add(PRODUCT ID)"
here, we will deal with all the cart actions in the next step.
STEP 3) AJAX CART HANDLER
// (A) INIT SHOPPING CART SESSION
session_start();
if (!isset($_SESSION["cart"])) { $_SESSION["cart"] = []; }
// (B) STANDARD RESPONSE
function respond ($status=1, $msg="") {
exit(json_encode(["status"=>$status, "msg"=>$msg]));
}
if (isset($_POST["req"])) { switch ($_POST["req"]) {
// (C) INVALID
default: respond(0, "Invalid Request");
// (D) ADD TO CART
case "add":
$qty = &$_SESSION["cart"][$_POST["pid"]];
if (isset($qty)) { $qty++; } else { $qty = 1; }
if ($qty > 99) { $qty = 99; }
respond();
// (E) CHANGE QUANTITY
case "set":
$qty = &$_SESSION["cart"][$_POST["pid"]];
$qty = $_POST["qty"];
if ($qty > 99) { $qty = 99; }
if ($qty <= 0) { unset($_SESSION["cart"][$_POST["pid"]]); }
respond();
// (F) REMOVE ITEM
case "del":
unset($_SESSION["cart"][$_POST["pid"]]);
respond();
// (G) NUKE
case "nuke":
$_SESSION["cart"] = [];
respond();
// (H) GET ALL ITEMS IN CART
case "get":
// (H1) EMPTY CART
if (count($_SESSION["cart"])==0) { respond(1, null); }
// (H2) FILTER ILLEGAL PRODUCTS
require "1-products.php";
$items = [];
foreach ($_SESSION["cart"] as $pid=>$qty) {
if (isset($products[$pid])) {
$items[$pid] = $products[$pid];
$items[$pid]["qty"] = $qty;
} else { unset($_SESSION["cart"][$pid]); }
}
if (count($_SESSION["cart"])==0) { respond(1, null); }
// (H3) RESPOND
respond(1, $items);
}}
Right, this part looks intimidating, but how it works is simple.
- We send a
$_POST["req"]
to this script, followed by the required parameters to perform a cart action. For example,$_POST = ["req"=>"set", "pid"=>1, "qty"=>11]
will set 11 apples in the cart. - The shopping cart is stored in
$_SESSION["cart"]
, in the format ofPRODUCT ID => QUANTITY
.
Request | Description & Parameters |
add |
Add an item to the cart.
|
set |
Set the item quantity.
|
del |
Remove an item from the cart.
|
nuke |
Clear the entire cart. |
get |
Get the contents and details of the current shopping cart. |
STEP 4) 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("3-ajax-cart.php", { method:"POST", body:form })
.then((res) => res.json()).then((res) => {
if (res.status!=1) { alert(res.msg); }
else if (after) { after(res.msg); }
}).catch((err) => {
alert("Error");
console.error(err);
});
},
// (B) SHOW ITEMS IN CART
show : () => {
cart.ajax({ req : "get" }, (items) => {
// (B1) GET HTML CART
let hcart = document.getElementById("cart");
hcart.innerHTML = "";
// (B2) EMPTY CART
if (items===null) { hcart.innerHTML = "Cart is empty."; }
// (B3) DRAW CART ITEMS
else {
let total = 0;
for (let [id, pdt] of Object.entries(items)) {
// ITEM ROW HTML ELEMENTS
let row = document.createElement("div"),
rowA = document.createElement("button"),
rowB = document.createElement("div"),
rowC = document.createElement("input");
// DELETE BUTTON
rowA.innerHTML = "X";
rowA.onclick = () => { cart.del(id); };
rowA.className = "cDel";
row.appendChild(rowA);
// NAME
rowB.innerHTML = pdt.name;
rowB.className = "cName";
row.appendChild(rowB);
// QUANTITY
rowC.type = "number";
rowC.value = pdt.qty;
rowC.min = 0; rowC.max = 99;
rowC.onchange = function () { cart.set(id, this.value); };
rowC.className = "cQty";
row.appendChild(rowC);
// ADD TO GRAND TOTAL
total += pdt.qty * pdt.price;
// ENTIRE ROW
row.className = "cRow";
hcart.appendChild(row);
}
// GRAND TOTAL
let row = document.createElement("div");
row.innerHTML = "TOTAL $" + total.toFixed(2);
row.className = "cTotal";
hcart.appendChild(row);
// CHECKOUT
row = document.createElement("button");
row.innerHTML = "Checkout";
row.className = "cOut";
row.onclick = () => { location.href = "5-order.php"; };
hcart.appendChild(row);
// EMPTY CART
row = document.createElement("button");
row.innerHTML = "Empty";
row.className = "cNuke";
row.onclick = cart.nuke;
hcart.appendChild(row);
}
});
},
// (C) ADD ITEM TO CART
add : (pid) => {
cart.ajax({ req : "add", pid : pid }, cart.show);
},
// (D) CHANGE QUANTITY
set : (pid, qty) => {
cart.ajax({ req : "set", pid : pid, qty : qty }, cart.show);
},
// (E) REMOVE ITEM
del : (pid) => {
cart.ajax({ req : "del", pid : pid }, cart.show);
},
// (F) NUKE
nuke : () => { if (confirm("Empty cart?")) {
cart.ajax({ req : "nuke" }, cart.show);
}}
};
window.addEventListener("DOMContentLoaded", cart.show);
Again, we have another seemingly difficult script. Keep calm and look carefully.
- (A)
ajax()
A helper function to do an AJAX call to the previous3-ajax-cart.php
. - (B)
show()
Get the contents of the cart, draw the HTML. - (C To F) All the cart actions.
add()
Add an item to the cart, update the HTML.set()
Change the quantity of an item, update the HTML.del()
Remove an item, update the HTML.nuke()
Empty the cart, update the HTML.
Easy?
STEP 5) ORDER PAGE
<form method="post" action="6-checkout.php" id="order">
<label for"name">Name</label>
<input type="text" name="name" required/>
<label for"name">Email</label>
<input type="email" name="email" required/>
<input type="submit" value="Place Order"/>
</form>
Next, we have a simple order form when the user clicks on “checkout”. Because there is no database, the only way is to capture the user details and send them out via email.
STEP 6) CHECKOUT
// (A) CHECKS
session_start();
if (!isset($_SESSION["cart"]) || count($_SESSION["cart"])==0) {
exit("Cart is empty");
}
if (!isset($_POST["name"]) || !isset($_POST["email"])) {
exit("Invalid request");
}
// (B) SEND EMAIL - CHANGE TO YOUR OWN!
$to = "admin@site.com";
$subject = "Order Received";
$body = "";
require "1-products.php";
foreach ($_SESSION["cart"] as $pid=>$qty) {
$body .= sprintf("%s X %s\r\n", $qty, $products[$pid]["name"]);
}
if (mail($to, $subject, $body)) {
echo "OK";
$_SESSION["cart"] = [];
} else { echo "ERROR"; }
Finally, this should be self-explanatory again – We simply collect the form data and cart items into an email.
USEFUL 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!