PHP Shopping Cart System with MySQL using SESSION

The shopping cart functionality is an important part of every e-commerce project. It helps the user to select and purchase multiple items at once. Also, the online shopping cart allows viewing the selected items and the total price before submitting the order. If you want to build a simple PHP shopping cart from scratch, this step-by-step tutorial will help you a lot. In this tutorial, we’ll provide the complete guide and example code to create a simple shopping cart in PHP using SESSION and MySQL.

A shopping cart is a must-have module for any eCommerce website. In this tutorial, you’ll learn how to build a fully functional shopping cart system in PHP using:

  • MySQL database (MySQLi)
  • PHP Sessions
  • AJAX (for add/update/remove actions)
  • A reusable Cart class to manage cart operations

This example shopping cart script is designed in a way that can be implemented easily in PHP application, and the tutorial makes it easy to understand the shopping cart concept in the web application. In our example script, we’ll use PHP session to store the product information in the cart. Once the order is submitted by the user, the product’s information will be inserted into the database using PHP and MySQL.

Features of the PHP Shopping Cart System

  • Display products from the database (MySQL)
  • Add products to the cart (PHP Sessions)
  • Update product quantity in the cart (PHP Sessions)
  • Remove products from the cart (PHP Sessions)
  • View cart items with total price (Cart class)
  • Checkout and place order (PHP + MySQL)

📁 Project Structure

Here is the project structure of the PHP shopping cart system:

shopping_cart_system_with_php/
├── index.php
├── product.php
├── cart.php
├── checkout.php
├── order_status.php
├── inc/
|   ├── config.php
|   ├── db.php
|   └── cart.class.php
├── api/
|   ├── cart_action.php
|   └── order_submit.php
└── assets/
    ├── js/
    |   └── cart.js
    ├── css/
    |   ├── bootstrap.min.css
    |   └── style.css
    └── images/
        └── product...images...

Create Database and Tables

Before we start coding, we need to create a MySQL database and the required tables. Below is the SQL code to create the database and tables for our shopping cart system.

Run the following SQL commands in your MySQL database management tool (like phpMyAdmin) to set up the database named shopping_cart_db (if you want to use existing database, you can skip this step):

CREATE DATABASE IF NOT EXISTS shopping_cart_db CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
USE shopping_cart_db;

Run the following SQL commands to create the required tables:

  • products: Stores product information (name, price, image, description, etc.)
  • orders: Contains order details (customer information, total amount, etc.)
  • order_items: Stores product-wise purchase details (product ID, quantity, price, etc.)
-- Products table
CREATE TABLE IF NOT EXISTS products (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  description TEXT NOT NULL,
  price DECIMAL(10,2) NOT NULL DEFAULT 0.00,
  image VARCHAR(255) DEFAULT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Orders table
CREATE TABLE IF NOT EXISTS orders (
  id INT AUTO_INCREMENT PRIMARY KEY,
  first_name VARCHAR(100) NOT NULL,
  last_name VARCHAR(100) NOT NULL,
  email VARCHAR(150) NOT NULL,
  phone VARCHAR(50) DEFAULT NULL,
  shipping_address TEXT NOT NULL,
  billing_address TEXT NOT NULL,
  total DECIMAL(10,2) NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Order items
CREATE TABLE IF NOT EXISTS order_items (
  id INT AUTO_INCREMENT PRIMARY KEY,
  order_id INT NOT NULL,
  product_id INT NOT NULL,
  name VARCHAR(255) NOT NULL,
  price DECIMAL(10,2) NOT NULL,
  quantity INT NOT NULL,
  subtotal DECIMAL(10,2) NOT NULL,
  FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE,
  FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE RESTRICT
);

Let’s insert some sample products into the products table to test our shopping cart:

INSERT INTO products (name, description, price, image) VALUES
('Classic T-Shirt', 'Comfortable cotton t-shirt. Available in multiple sizes and colors.', 19.99, 'assets/images/product1.jpg'),
('Sneakers', 'Lightweight running sneakers with breathable mesh upper.', 59.99, 'assets/images/product2.jpg'),
('Coffee Mug', 'Ceramic mug with 350ml capacity. Dishwasher safe.', 9.50, 'assets/images/product3.jpg');

Configuration File (inc/config.php)

Create a configuration file named config.php in the inc directory. This file will contain the database connection settings and other configurations.

<?php 
// Database configuration - update with your local DB credentials
define('DB_HOST''localhost');
define('DB_USER''root');
define('DB_PASS''');
define('DB_NAME''shopping_cart_db');

// From email for notifications (update if needed)
define('FROM_EMAIL''no-reply@example.com');
?>

Database Connection (inc/db.php)

Create a database connection file named db.php in the inc directory. This file will establish a connection to the MySQL database using the configuration settings defined in config.php.

<?php 
require_once __DIR__ '/config.php';

// Function to get a mysqli database connection
function get_db()
{
    static 
$mysqli null;
    if (
$mysqli === null) {
        
$mysqli = new mysqli(DB_HOSTDB_USERDB_PASSDB_NAME);
        if (
$mysqli->connect_errno) {
            die(
'Database connection failed: ' $mysqli->connect_error);
        }
        
$mysqli->set_charset('utf8mb4');
    }
    return 
$mysqli;
}

?>

Building the Cart Class (inc/cart.class.php)

Create a file named cart.class.php in the inc directory. This file will contain the Cart class that manages cart operations such as adding, updating, and removing items from the cart.

This is the core engine of the shopping cart. The class uses $_SESSION['cart'] to store:

  • product IDs
  • quantity
  • price
  • subtotal

The Cart class includes methods like:

  • add($product_id, $qty): Adds a new product to the cart or increments existing quantity.
  • update($product_id, $qty): Updates quantity for a cart item.
  • remove($product_id): Removes selected product from cart.
  • items(): Returns all cart items along with product data (fetched from DB).
  • total(): Calculates the total price of all items.
  • count(): Shows item count.
  • clear(): Empties the cart after order submission.

This Cart library keeps the system clean and reusable.

<?php 
require_once __DIR__ '/db.php';

class 
Cart
{
    public function 
__construct()
    {
        if (
session_status() === PHP_SESSION_NONE) {
            
session_start();
        }
        if (!isset(
$_SESSION['cart'])) {
            
$_SESSION['cart'] = [];
        }
    }

    public function 
add($product_id$qty 1)
    {
        
$db get_db();
        
$product_id = (int)$product_id;
        
$qty max(1, (int)$qty);

        
// Validate product exists
        
$stmt $db->prepare('SELECT id FROM products WHERE id = ? LIMIT 1');
        
$stmt->bind_param('i'$product_id);
        
$stmt->execute();
        
$res $stmt->get_result();
        if (
$res->num_rows === 0) {
            return 
false;
        }

        if (isset(
$_SESSION['cart'][$product_id])) {
            
$_SESSION['cart'][$product_id] += $qty;
        } else {
            
$_SESSION['cart'][$product_id] = $qty;
        }
        return 
true;
    }

    public function 
update($product_id$qty)
    {
        
$product_id = (int)$product_id;
        
$qty = (int)$qty;
        if (
$qty <= 0) {
            return 
$this->remove($product_id);
        }
        if (isset(
$_SESSION['cart'][$product_id])) {
            
$_SESSION['cart'][$product_id] = $qty;
            return 
true;
        }
        return 
false;
    }

    public function 
remove($product_id)
    {
        
$product_id = (int)$product_id;
        if (isset(
$_SESSION['cart'][$product_id])) {
            unset(
$_SESSION['cart'][$product_id]);
            return 
true;
        }
        return 
false;
    }

    public function 
items()
    {
        
$db get_db();
        
$items = [];
        if (empty(
$_SESSION['cart'])) return $items;
        
$ids array_keys($_SESSION['cart']);
        
$placeholders implode(','array_fill(0count($ids), '?'));
        
$types str_repeat('i'count($ids));

        
$sql "SELECT id, name, price, image, description FROM products WHERE id IN ($placeholders)";
        
$stmt $db->prepare($sql);
        
$stmt->bind_param($types, ...$ids);
        
$stmt->execute();
        
$res $stmt->get_result();
        while (
$row $res->fetch_assoc()) {
            
$pid = (int)$row['id'];
            
$qty = isset($_SESSION['cart'][$pid]) ? (int)$_SESSION['cart'][$pid] : 0;
            
$row['quantity'] = $qty;
            
$row['subtotal'] = $qty * (float)$row['price'];
            
$items[$pid] = $row;
        }
        return 
$items;
    }

    public function 
total()
    {
        
$total 0.0;
        foreach (
$this->items() as $item) {
            
$total += $item['subtotal'];
        }
        return 
$total;
    }

    public function 
count()
    {
        
$count 0;
        foreach (
$_SESSION['cart'] as $qty) {
            
$count += $qty;
        }
        return 
$count;
    }

    public function 
clear()
    {
        
$_SESSION['cart'] = [];
    }
}

Displaying Products (index.php)

Create an index.php file to display the products fetched from the database. This file will also include the “Add to Cart” functionality.

This page loads the product list using a database query:

  • Fetches all products from products table
  • Displays product image, name, price
  • Includes “Add to Cart” button connected to AJAX request → /api/cart_action.php

Typical UI features:

  • Bootstrap-based grid
  • “View Details” button linking to product.php?id=ID
<?php 
// Include configuration and necessary files
require_once __DIR__ '/inc/db.php';
require_once 
__DIR__ '/inc/cart.class.php';

// Initialize cart and database connection
$cart = new Cart();
$db get_db();

// Fetch products from the database
$res $db->query('SELECT id, name, price, image, description FROM products ORDER BY id DESC');
?> <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Product List</title> <!-- Bootstrap library --> <link href="assets/css/bootstrap.min.css" rel="stylesheet"> <!-- Custom styles --> <link href="assets/css/style.css" rel="stylesheet"> </head> <body> <nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top shadow-sm"> <div class="container"> <a class="navbar-brand" href="#">My Shop</a> <div> <!-- Cart button with item count --> <a href="cart.php" class="btn btn-outline-primary"> Cart <span id="cart-count" class="badge bg-primary"><?php echo $cart->count(); ?></span> </a> </div> </div> </nav> <div class="container mt-4"> <div class="row g-3">     <?php 
    
// Loop through products and display them
    
if($res->num_rows 0):
      while(
$p $res->fetch_assoc()):
    
?> <div class="col-sm-6 col-md-4"> <div class="product-card"> <a href="product.php?id=<?php echo $p['id']; ?>"> <img src="<?php echo htmlspecialchars($p['image']); ?>" alt="<?php echo htmlspecialchars($p['name']); ?>" class="product-image"> </a> <div class="card-body"> <h5><a href="product.php?id=<?php echo $p['id']; ?>"><?php echo htmlspecialchars($p['name']); ?></a></h5> <p class="text-muted">$<?php echo number_format($p['price'], 2); ?></p> <p><?php echo htmlspecialchars(substr($p['description'], 080)); ?>...</p> <div class="d-flex gap-2"> <button class="btn btn-primary btn-add-cart" data-product-id="<?php echo $p['id']; ?>"><i class="fa fa-cart-plus"></i> Add to Cart</button> </div> </div> </div> </div>     <?php
      
endwhile;
    else:
      echo 
"<p>No products found.</p>";
    endif;
    
?> </div> </div> <!-- JavaScript for cart functionality --> <script src="assets/js/cart.js"></script> </body> </html>

Product Details Page (product.php)

Create a product.php file to display detailed information about a specific product. This page will be accessed via a URL parameter (e.g., product.php?id=1).

It reads the id from the query parameter and then fetches product details from the DB and renders them. This page shows:

  • Product image
  • Description
  • Full specifications
  • Price
  • Quantity selector
  • Add to cart button: The “Add to Cart” button sends an AJAX request → /api/cart_action.php.
<?php 
// Include configuration and necessary files
require_once __DIR__ '/inc/db.php';
require_once 
__DIR__ '/inc/cart.class.php';

// Initialize cart and database connection
$cart = new Cart();
$db get_db();

// Get product ID from query parameter
$id filter_input(INPUT_GET'id'FILTER_VALIDATE_INT);
if (!
$id) die('Product not found');

// Fetch product details from the database
$stmt $db->prepare('SELECT id, name, description, price, image FROM products WHERE id = ? LIMIT 1');
$stmt->bind_param('i'$id);
$stmt->execute();
$res $stmt->get_result();
if (
$res->num_rows === 0) die('Product not found');
$p $res->fetch_assoc();
?> <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title><?php echo htmlspecialchars($p['name']); ?></title> <!-- Bootstrap library --> <link href="assets/css/bootstrap.min.css" rel="stylesheet"> <!-- Custom styles --> <link href="assets/css/style.css" rel="stylesheet"> </head> <body> <nav class="navbar navbar-expand-lg navbar-light bg-white fixed-top shadow-sm"> <div class="container"> <a class="navbar-brand" href="index.php">My Shop</a> <div> <!-- Cart button with item count --> <a href="cart.php" class="btn btn-outline-primary"> Cart <span id="cart-count" class="badge bg-primary"><?php echo $cart->count(); ?></span> </a> </div> </div> </nav> <div class="row"> <div class="col-md-6"> <img src="<?php echo htmlspecialchars($p['image']); ?>" class="img-fluid" alt="<?php echo htmlspecialchars($p['name']); ?>"> </div> <div class="col-md-6"> <h2><?php echo htmlspecialchars($p['name']); ?></h2> <p class="text-muted">$<?php echo number_format($p['price'], 2); ?></p> <p><?php echo nl2br(htmlspecialchars($p['description'])); ?></p> <div class="d-flex gap-2 align-items-center"> <input type="number" id="qty-<?php echo $p['id']; ?>" min="1" value="1" class="form-control" style="width:100px"> <button class="btn btn-success btn-add-cart" data-product-id="<?php echo $p['id']; ?>">Add to Cart</button> </div> </div> </div> </div> <!-- JavaScript for cart functionality --> <script src="assets/js/cart.js"></script> </body> </html>

Shopping Cart Page (cart.php)

The cart page (cart.php) displays all items added to the cart, allowing users to update quantities or remove items. It also shows the total price and a checkout button.

  • At the top, it initializes the Cart class and retrieves cart items from the session.
  • It then loops through the cart items, fetching product details from the database for each item.
  • The page displays each item’s name, price, quantity (with an input field to update), and subtotal. It also calculates and displays the total price for all items in the cart.
  • Finally, it includes JavaScript to handle quantity updates and item removals via AJAX (request → /api/cart_action.php).
<?php 
// Include library and initialize cart
require_once __DIR__ '/inc/cart.class.php';
$cart = new Cart();

// Retrieve cart items from session
$items $cart->items();
?> <div class="container mt-4"> <!-- Display cart items or empty message --> <?php if (empty($items)): ?> <div class="alert alert-info">Your cart is empty. <a href="index.php">Continue shopping</a>.</div> <?php else: ?> <div class="table-responsive"> <table class="table align-middle"> <thead> <tr> <th width="43%">Product</th> <th width="15%">Price</th> <th width="15%">Quantity</th> <th width="20%">Subtotal</th> <th width="7%"></th> </tr> </thead> <tbody> <?php foreach ($items as $it): ?> <tr data-id="<?php echo $it['id']; ?>"> <td> <div class="d-flex align-items-center"> <img src="<?php echo htmlspecialchars($it['image']); ?>" class="img-thumb me-2" alt=""> <div> <a href="product.php?id=<?php echo $it['id']; ?>"><?php echo htmlspecialchars($it['name']); ?></a> </div> </div> </td> <td>$<?php echo number_format($it['price'],2); ?></td> <td> <input type="number" class="form-control qty-input" value="<?php echo $it['quantity']; ?>" min="1" data-id="<?php echo $it['id']; ?>"> </td> <td class="subtotal">$<?php echo number_format($it['subtotal'],2); ?></td> <td> <button class="btn btn-danger btn-remove" data-id="<?php echo $it['id']; ?>"><i class="fa fa-trash"></i></button> </td> </tr> <?php endforeach; ?> </tbody> <tfoot> <tr> <td colspan="3" class="text-end"><strong>Total</strong></td> <td colspan="2"><strong>$<?php echo number_format($cart->total(),2); ?></strong></td> </tr> </tfoot> </table> </div> <?php endif; ?> </div> <script> // Small AJAX handlers using fetch function postForm(data) { return fetch('api/cart_action.php', { method: 'POST', body: data }).then(r => r.json()); } // Handle quantity changes and item removals document.addEventListener('DOMContentLoaded', function(){ document.querySelectorAll('.qty-input').forEach(function(el){ el.addEventListener('change', function(){ const id = this.dataset.id; const qty = parseInt(this.value) || 1; const fd = new FormData(); fd.append('action','update'); fd.append('product_id', id); fd.append('quantity', qty); postForm(fd).then(resp => { if (resp.success) location.reload(); else alert(resp.message || 'Update failed'); }); }); }); document.querySelectorAll('.btn-remove').forEach(function(btn){ btn.addEventListener('click', function(){ if (!confirm('Remove this item?')) return; const id = this.dataset.id; const fd = new FormData(); fd.append('action','remove'); fd.append('product_id', id); postForm(fd).then(resp => { if (resp.success) location.reload(); else alert('Failed'); }); }); }); }); </script>

AJAX Cart Operations (api/cart_action.php)

Create a file named cart_action.php in the api directory. This script handles AJAX requests to add, update, or remove items from the shopping cart. It expects POST requests with an action parameter and relevant data.

  • Include Cart Class: The script includes the cart class and initializes a cart object.
  • Set Response Header: It sets the response header to indicate that the response will be in JSON format.
  • Get Action: The action to be performed (add, update, remove) is retrieved from the POST data.
  • Handle Actions: Based on the action, the script performs the corresponding cart operation:
    • Add: Validates product ID and quantity, adds the item to the cart, and returns a success message.
    • Update: Validates product ID and quantity, updates the item quantity in the cart, and returns a success message.
    • Remove: Validates product ID, removes the item from the cart, and returns a success message.
  • Error Handling: If any validation fails or an exception occurs, an error message is returned in the JSON response.
<?php 
// Include cart class and initialize cart
require_once __DIR__ '/../inc/cart.class.php';
$cart = new Cart();

// Set response header for JSON
header('Content-Type: application/json; charset=utf-8');

// Get action from POST data
$action $_POST['action'] ?? '';

// Handle different cart actions (add, update, remove)
try {
    
// Add item to cart
    
if ($action === 'add') {
        
$product_id filter_input(INPUT_POST'product_id'FILTER_VALIDATE_INT);
        
$qty filter_input(INPUT_POST'quantity'FILTER_VALIDATE_INT) ?: 1;
        if (!
$product_id) throw new Exception('Invalid product id');
        
$ok $cart->add($product_id$qty);
        if (!
$ok) throw new Exception('Product not found');
        echo 
json_encode(['success' => true'count' => $cart->count()]);
        exit;
    }

    
// Update item quantity in cart
    
if ($action === 'update') {
        
$product_id filter_input(INPUT_POST'product_id'FILTER_VALIDATE_INT);
        
$qty filter_input(INPUT_POST'quantity'FILTER_VALIDATE_INT);
        if (!
$product_id || $qty === null) throw new Exception('Invalid input');
        
$ok $cart->update($product_id$qty);
        echo 
json_encode(['success' => $ok'total' => $cart->total()]);
        exit;
    }

    
// Remove item from cart
    
if ($action === 'remove') {
        
$product_id filter_input(INPUT_POST'product_id'FILTER_VALIDATE_INT);
        if (!
$product_id) throw new Exception('Invalid product id');
        
$ok $cart->remove($product_id);
        echo 
json_encode(['success' => $ok'total' => $cart->total(), 'count' => $cart->count()]);
        exit;
    }

    echo 
json_encode(['success' => false'message' => 'Unknown action']);
} catch (
Exception $e) {
    echo 
json_encode(['success' => false'message' => $e->getMessage()]);
}

Checkout Page (checkout.php)

This page displays the checkout form and processes user input for completing the purchase. It retrieves cart items from the session and handles validation errors and old inputs.

  • Session Management: The script ensures that a session is started to access validation errors and old input data.
  • Include Cart Class: It includes the cart class and initializes a cart object.
  • Retrieve Cart Items: The cart items are retrieved from the session. If the cart is empty, the user is redirected to the index page.
  • Validation Errors and Old Inputs: Any validation errors and old input values from a previous submission are retrieved from the session and then cleared.

The form submits order details via AJAX to api/order_submit.php.

<?php 
// ensure session available for validation errors / old inputs
if (session_status() === PHP_SESSION_NONEsession_start();

// Include library and initialize cart
require_once __DIR__ '/inc/cart.class.php';
$cart = new Cart();

// Retrieve cart items from session
$items $cart->items();
if (empty(
$items)) {
  
header('Location: index.php'); exit;
}

// grab validation errors and old inputs from session (if any)
$errors $_SESSION['checkout_errors'] ?? [];
$old $_SESSION['checkout_old'] ?? [];
unset(
$_SESSION['checkout_errors'], $_SESSION['checkout_old']);
?> <div class="container mt-4"> <div class="row"> <div class="col-md-7"> <h3>Buyer Information</h3> <!-- Display validation errors if any --> <?php if (!empty($errors)): ?> <div class="alert alert-danger"> <ul class="mb-0"> <?php foreach ($errors as $err): ?> <li><?php echo htmlspecialchars($err); ?></li> <?php endforeach; ?> </ul> </div> <?php endif; ?> <!-- Checkout form --> <form method="post" action="api/order_submit.php"> <div class="row"> <div class="col-md-6 mb-3"> <input name="first_name" class="form-control" placeholder="First name" required value="<?php echo $old['first_name'] ?? ''?>"> </div> <div class="col-md-6 mb-3"> <input name="last_name" class="form-control" placeholder="Last name" required value="<?php echo $old['last_name'] ?? ''?>"> </div> </div> <div class="mb-3"> <input name="email" type="email" class="form-control" placeholder="Email" required value="<?php echo $old['email'] ?? ''?>"> </div> <div class="mb-3"> <input name="phone" class="form-control" placeholder="Phone" value="<?php echo $old['phone'] ?? ''?>"> </div> <div class="mb-3"> <textarea name="shipping_address" class="form-control" rows="3" placeholder="Shipping address" required><?php echo $old['shipping_address'] ?? ''?></textarea> </div> <div class="mb-3"> <textarea name="billing_address" class="form-control" rows="3" placeholder="Billing address" required><?php echo $old['billing_address'] ?? ''?></textarea> </div> <button class="btn btn-success" type="submit">Place Order</button> </form> </div> <div class="col-md-5"> <h4>Cart Summary <small class="text-muted">(<?php echo $cart->count(); ?> items)</small></h4> <div class="cart-summary"> <?php foreach ($items as $it): ?> <div class="d-flex align-items-center mb-3" data-id="<?php echo $it['id']; ?>"> <img src="<?php echo htmlspecialchars($it['image']); ?>" class="img-thumb me-3" alt=""> <div class="flex-grow-1"> <div class="fw-semibold"><?php echo htmlspecialchars($it['name']); ?></div> <div class="text-muted small">Price: $<?php echo number_format($it['price'],2); ?> &nbsp;•&nbsp; Qty: <?php echo $it['quantity']; ?> &nbsp;•&nbsp; Subtotal: $<?php echo number_format($it['subtotal'],2); ?></div> </div> </div> <?php endforeach; ?> <hr> <div class="d-flex justify-content-between mb-2"><strong>Total</strong><strong>$<?php echo number_format($cart->total(),2); ?></strong></div> </div> </div> </div> </div>

Order Submission (api/order_submit.php)

Create a file named order_submit.php in the api directory. This script processes the order submission. It includes server-side validation, cart retrieval, and order storage in the database.

  • Includes necessary files for cart management, database connection, and configuration.
  • Starts a session to store errors and old input data.
  • Initializes the cart and retrieves cart items. If the cart is empty, it sets an error message and redirects back to the checkout page.
  • Performs basic server-side validation and sanitization of user input (first name, last name, email, phone, shipping address, billing address).
  • Insert order and order items into the database (MySQLi prepared statements).
  • Sends order confirmation email to the user using PHP’s mail function.
  • Clears the cart upon successful order placement and redirects to an order status page (order_status.php?order_id={$order_id}).
<?php 
// Include necessary files
require_once __DIR__ '/../inc/cart.class.php';
require_once 
__DIR__ '/../inc/db.php';
require_once 
__DIR__ '/../inc/config.php';

// Start session to store errors and old input
if (session_status() === PHP_SESSION_NONEsession_start();

// Initialize cart 
$cart = new Cart();

// Retrieve cart items
$items $cart->items();
if (empty(
$items)) {
    
// set an error and redirect back to checkout (or index)
    
$_SESSION['checkout_errors'] = ['Your cart is empty.'];
    
header('Location: ../checkout.php');
    exit;
}

// Basic server-side validation and sanitization
$first_name trim($_POST['first_name'] ?? '');
$last_name trim($_POST['last_name'] ?? '');
$email filter_var($_POST['email'] ?? ''FILTER_VALIDATE_EMAIL);
$phone trim($_POST['phone'] ?? '');
$shipping trim($_POST['shipping_address'] ?? '');
$billing trim($_POST['billing_address'] ?? '');

$errors = [];
if (!
$first_name$errors[] = 'First name is required';
if (!
$last_name$errors[] = 'Last name is required';
if (!
$email$errors[] = 'Valid email is required';
if (!
$shipping$errors[] = 'Shipping address is required';
if (!
$billing$errors[] = 'Billing address is required';

if (!empty(
$errors)) {
    
// store errors and old input in session then redirect back to checkout
    
$_SESSION['checkout_errors'] = $errors;
    
$_SESSION['checkout_old'] = [
        
'first_name' => htmlspecialchars($first_nameENT_QUOTES ENT_SUBSTITUTE'UTF-8'),
        
'last_name' => htmlspecialchars($last_nameENT_QUOTES ENT_SUBSTITUTE'UTF-8'),
        
'email' => $email ?: '',
        
'phone' => htmlspecialchars($phoneENT_QUOTES ENT_SUBSTITUTE'UTF-8'),
        
'shipping_address' => htmlspecialchars($shippingENT_QUOTES ENT_SUBSTITUTE'UTF-8'),
        
'billing_address' => htmlspecialchars($billingENT_QUOTES ENT_SUBSTITUTE'UTF-8'),
    ];
    
header('Location: ../checkout.php');
    exit;
}

// Insert order and order items into database
$db get_db();
$db->begin_transaction();
try {
    
$total $cart->total();
    
$stmt $db->prepare('INSERT INTO orders (first_name, last_name, email, phone, shipping_address, billing_address, total) VALUES (?, ?, ?, ?, ?, ?, ?)');
    
$stmt->bind_param('ssssssd'$first_name$last_name$email$phone$shipping$billing$total);
    
$stmt->execute();
    
$order_id $db->insert_id;

    
$item_stmt $db->prepare('INSERT INTO order_items (order_id, product_id, name, price, quantity, subtotal) VALUES (?, ?, ?, ?, ?, ?)');
    foreach (
$items as $pid => $item) {
        
$subtotal $item['subtotal'];
        
$pname $item['name'];
        
$pprice $item['price'];
        
$pqty $item['quantity'];
        
$item_stmt->bind_param('iisdid'$order_id$pid$pname$pprice$pqty$subtotal);
        
$item_stmt->execute();
    }

    
$db->commit();

    
// Send a basic email notification (may require local mail configuration)
    
$to $email;
    
$subject 'Order Confirmation #' $order_id;
    
$message "Thank you for your order. Order ID: $order_id\n\n";
    foreach (
$items as $it) {
        
$message .= $it['name'] . ' x ' $it['quantity'] . ' - $' number_format($it['subtotal'], 2) . "\n";
    }
    
$message .= "\nTotal: $" number_format($total2) . "\n";
    
$headers 'From: ' FROM_EMAIL "\r\n";
    @
mail($to$subject$message$headers);

    
// Clear cart and redirect to order status
    
$cart->clear();
    
header('Location: ../order_status.php?order_id=' $order_id);
    exit;
} catch (
Exception $e) {
    
$db->rollback();
    die(
'Order submission failed: ' $e->getMessage());
}

Order Status Page (order_status.php)

This page displays the status of a specific order based on the order ID provided in the query parameters. It retrieves order details from the database and shows whether the order is pending, completed, or canceled.

<?php 
// Include configuration and necessary files
require_once __DIR__ '/inc/db.php';
require_once 
__DIR__ '/inc/cart.class.php';

// Initialize cart and database connection
$cart = new Cart();
$db get_db();

// Get order ID from query parameter
$order_id filter_input(INPUT_GET'order_id'FILTER_VALIDATE_INT);
if (!
$order_id) die('Order id missing');

// Fetch order details from the database
$stmt $db->prepare('SELECT * FROM orders WHERE id = ? LIMIT 1');
$stmt->bind_param('i'$order_id);
$stmt->execute();
$order $stmt->get_result()->fetch_assoc();
if (!
$order) die('Order not found');

// Fetch order items with product image if available
$itst $db->prepare('SELECT oi.*, p.image FROM order_items oi LEFT JOIN products p ON oi.product_id = p.id WHERE oi.order_id = ?');
$itst->bind_param('i'$order_id);
$itst->execute();
$items $itst->get_result()->fetch_all(MYSQLI_ASSOC);
?> <div class="container mt-4"> <div class="py-3 text-center"> <h2>Order Confirmation</h2> <p class="lead">Below is an example of an order status screen. This screen displays the order submission status to the user.</p> </div> <div class="col-md-12"> <div class="alert alert-success"> Thank you, <?php echo htmlspecialchars($order['first_name'] . ' ' $order['last_name']); ?>. Your order #<?php echo $order['id']; ?> has been received. </div> </div> <div class="col-md-12 ord-info"> <h4>Order Details</h4> <ul> <li>Order ID: <?php echo $order['id']; ?></li> <li>Date: <?php echo $order['created_at']; ?></li> <li>Total: $<?php echo number_format($order['total'],2); ?></li> </ul> </div> </div>

Frontend JavaScript (assets/js/cart.js)

This JavaScript file provides AJAX helper functions to manage cart operations such as adding items, updating quantities, and removing items from the cart without reloading the page.

AJAX improves usability and avoids page reloads for cart actions. Handled features include:

  • Add to cart
  • Update quantity
  • Remove item
  • Update cart counter instantly
  • Display notification messages (success/error)
// Simple AJAX helpers for cart operations
function ajaxPost(url, data) {
    return fetch(url, { method: 'POST', body: data })
        .then(res => res.json());
}

// Add item to cart
function addToCart(productId, qty) {
    const fd = new FormData();
    fd.append('action', 'add');
    fd.append('product_id', productId);
    fd.append('quantity', qty || 1);
    return ajaxPost('api/cart_action.php', fd);
}

// Update cart item quantity
function updateCart(productId, qty) {
    const fd = new FormData();
    fd.append('action', 'update');
    fd.append('product_id', productId);
    fd.append('quantity', qty);
    return ajaxPost('api/cart_action.php', fd);
}

// Remove item from cart
function removeFromCart(productId) {
    const fd = new FormData();
    fd.append('action', 'remove');
    fd.append('product_id', productId);
    return ajaxPost('api/cart_action.php', fd);
}

// Bind UI helpers
document.addEventListener('click', function (e) {
    if (e.target.matches('.btn-add-cart')) {
        e.preventDefault();
        const pid = e.target.dataset.productId;
        const qtyEl = document.querySelector('#qty-' + pid);
        const qty = qtyEl ? parseInt(qtyEl.value) || 1 : 1;
        addToCart(pid, qty).then(resp => {
            if (resp.success) {
                // Update cart count if present
                const el = document.querySelector('#cart-count');
                if (el) el.textContent = resp.count || '';
                alert('Added to cart');
            } else {
                alert(resp.message || 'Failed to add');
            }
        });
    }
});

🎉 Conclusion

This PHP Shopping Cart System is lightweight, fast, and perfect for small-to-medium eCommerce stores. It covers essential features like product listing, cart management, and order processing while being easy to set up and customize. This Shopping Cart System with PHP is Bootstrap-based, so design customization is easy. Also, custom Cart library class makes it easy to manage cart operations. Here are some key features:

  • Lightweight and fast PHP Shopping Cart System
  • Essential eCommerce features covered
  • Easy to set up and customize
  • Bootstrap-based design for easy customization
  • Modular structure for easy maintenance and scalability

You can further enhance this system by integrating payment gateways, adding user authentication, and implementing advanced features like product reviews and wishlists. The modular structure allows for easy maintenance and scalability.

Happy coding! 🚀

Looking for expert assistance to implement or extend this script’s functionality? Submit a Service Request

40 Comments

  1. Rohan Said...
  2. Sarah Karamsi Said...
  3. Satish Pawar Said...
  4. Dre Said...
  5. Ponmalar Said...
  6. ELYAR SEMI Said...
  7. Imali Said...
  8. Bogus Name Said...
  9. Shawn Mckenzie Said...
  10. Chris Clement Said...
  11. Sebastien Plante Said...
  12. Kiran Said...
  13. Cath Said...
  14. Hell Is Rare Said...
  15. SRAVAN KUMAR Said...
  16. Website Dzyner Said...
  17. Tayyaba Said...
  18. Nick Said...
  19. Willy Said...
  20. Ajit Rajaram Chaware Said...
  21. Mahdev Prasad Said...
  22. Sid Said...
    • CodexWorld Said...
  23. Mimi Said...
    • CodexWorld Said...
  24. Kalai Said...
  25. Chris Said...
  26. Rishav Basu Said...
    • CodexWorld Said...
  27. Jstyles Said...
  28. Anu Said...
    • CodexWorld Said...
  29. Leon Yew Said...
  30. Johnny Said...
  31. Harold Rau Said...
  32. Satyanarayan Said...
    • CodexWorld Said...
  33. Zionsoft Said...
  34. Sami Said...

Leave a reply

construction Need this implemented in your project? Request Implementation Help → keyboard_double_arrow_up