E-Commerce website project built with HTML, CSS, JavaScript, PHP, and MySQL

πŸ›’ Project Introduction: Basic E-Commerce Website

This project is a fully functional Basic E-Commerce Website that allows customers to browse products, add them to a cart, and proceed to checkout. It also includes a password-protected Admin Panel for the store owner to manage the product inventory.

The Problem it Solves:
Small business owners often need a simple online store without the complexity of large platforms like Shopify or Magento. This system provides a lightweight, self-hosted solution where the owner can easily add, update, or remove products through an admin interface, and customers can make purchases.

Key Features:

  • Customer Side (Public View):
    • Product Catalog: Displays all products with images, names, prices, and descriptions.
    • Product Categories: Filter products by category.
    • Shopping Cart: Add/remove products, update quantities, and view total price.
    • Checkout Page: Collect customer information and place orders.
    • Order Confirmation: Display order summary after successful checkout.
    • Responsive Design: Works on mobile, tablet, and desktop.
  • Admin Side (Private Panel):
    • Secure Login: Password-protected access.
    • Dashboard: Overview of total products, orders, and revenue.
    • Product Management: Add, Edit, and Delete products (name, price, description, image, category).
    • Order Management: View all customer orders and update order status (Pending, Completed, Cancelled).
    • Category Management: Add, Edit, and Delete product categories.
    • Logout Functionality.

Technology Stack:

  • Frontend: HTML5, CSS3, JavaScript (Vanilla JS for cart functionality).
  • Backend: PHP (Core PHP for CRUD operations and session management).
  • Database: MySQL.
  • Server: Apache (XAMPP/WAMP/LAMP).

πŸ“ Project File Structure

Create this structure in your server's root directory (e.g., htdocs for XAMPP).

ecommerce-basic/
β”‚
β”œβ”€β”€ index.php                 # Public homepage - Product listing
β”œβ”€β”€ product.php               # Single product details page
β”œβ”€β”€ cart.php                  # Shopping cart page
β”œβ”€β”€ checkout.php              # Checkout page
β”œβ”€β”€ order-confirmation.php    # Order success page
β”œβ”€β”€ login.php                 # Customer login/register (optional)
β”œβ”€β”€ logout.php                # Logout script
β”‚
β”œβ”€β”€ admin/                    # Admin Panel Directory
β”‚   β”œβ”€β”€ index.php             # Admin Login Page
β”‚   β”œβ”€β”€ dashboard.php         # Admin Dashboard
β”‚   β”œβ”€β”€ products.php          # Manage products (CRUD)
β”‚   β”œβ”€β”€ add-product.php       # Add new product form
β”‚   β”œβ”€β”€ edit-product.php      # Edit product form
β”‚   β”œβ”€β”€ delete-product.php    # Delete product script
β”‚   β”œβ”€β”€ categories.php        # Manage categories
β”‚   β”œβ”€β”€ orders.php            # View all orders
β”‚   β”œβ”€β”€ logout.php            # Admin logout
β”‚   └── css/
β”‚       └── admin-style.css   # Admin panel styles
β”‚
β”œβ”€β”€ includes/                  # Backend PHP logic
β”‚   β”œβ”€β”€ config.php             # Database connection
β”‚   β”œβ”€β”€ functions.php          # Helper functions
β”‚   β”œβ”€β”€ auth.php               # Admin authentication check
β”‚   β”œβ”€β”€ header.php             # Public site header
β”‚   └── footer.php             # Public site footer
β”‚
β”œβ”€β”€ assets/                    # Static assets
β”‚   β”œβ”€β”€ css/
β”‚   β”‚   └── style.css          # Main CSS for public site
β”‚   β”œβ”€β”€ js/
β”‚   β”‚   └── script.js          # Main JS (cart functionality)
β”‚   └── images/
β”‚       β”œβ”€β”€ products/          # Product images (uploaded here)
β”‚       └── placeholder.jpg    # Default image
β”‚
└── database/
└── ecommerce.sql          # Database dump file

πŸ—„οΈ Database Setup (database/ecommerce.sql)

Create a database named ecommerce_db and run this SQL.

-- phpMyAdmin SQL Dump
-- Database: `ecommerce_db`
CREATE DATABASE IF NOT EXISTS `ecommerce_db`;
USE `ecommerce_db`;
-- --------------------------------------------------------
-- Table structure for table `categories`
-- --------------------------------------------------------
CREATE TABLE `categories` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`description` text DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Sample categories
INSERT INTO `categories` (`name`, `description`) VALUES
('Electronics', 'Gadgets, devices, and electronic accessories'),
('Clothing', 'Fashionable apparel for men and women'),
('Books', 'Bestsellers and timeless classics');
-- --------------------------------------------------------
-- Table structure for table `products`
-- --------------------------------------------------------
CREATE TABLE `products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`category_id` int(11) DEFAULT NULL,
`name` varchar(200) NOT NULL,
`description` text NOT NULL,
`price` decimal(10,2) NOT NULL,
`image` varchar(255) DEFAULT 'placeholder.jpg',
`stock` int(11) NOT NULL DEFAULT 0,
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
KEY `category_id` (`category_id`),
CONSTRAINT `products_ibfk_1` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Sample products
INSERT INTO `products` (`category_id`, `name`, `description`, `price`, `image`, `stock`) VALUES
(1, 'Wireless Headphones', 'High-quality wireless headphones with noise cancellation.', 79.99, 'headphones.jpg', 25),
(1, 'Smart Watch', 'Track your fitness and stay connected.', 199.99, 'smartwatch.jpg', 15),
(2, 'Cotton T-Shirt', 'Comfortable 100% cotton t-shirt, available in multiple colors.', 24.99, 'tshirt.jpg', 50),
(3, 'The Great Novel', 'A captivating story that will keep you hooked.', 14.99, 'novel.jpg', 100);
-- --------------------------------------------------------
-- Table structure for table `orders`
-- --------------------------------------------------------
CREATE TABLE `orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`customer_name` varchar(100) NOT NULL,
`customer_email` varchar(100) NOT NULL,
`customer_address` text NOT NULL,
`total_amount` decimal(10,2) NOT NULL,
`status` enum('pending','processing','completed','cancelled') DEFAULT 'pending',
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- --------------------------------------------------------
-- Table structure for table `order_items`
-- --------------------------------------------------------
CREATE TABLE `order_items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_id` int(11) NOT NULL,
`product_id` int(11) NOT NULL,
`product_name` varchar(200) NOT NULL,
`quantity` int(11) NOT NULL,
`price` decimal(10,2) NOT NULL,
PRIMARY KEY (`id`),
KEY `order_id` (`order_id`),
CONSTRAINT `order_items_ibfk_1` FOREIGN KEY (`order_id`) REFERENCES `orders` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- --------------------------------------------------------
-- Table structure for table `admin`
-- --------------------------------------------------------
CREATE TABLE `admin` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Default admin: username = admin, password = admin123 (hashed)
-- You need to hash this manually or use a script
INSERT INTO `admin` (`username`, `password`) VALUES
('admin', '$2y$10$YourHashedPasswordHere'); -- Replace with actual hash
COMMIT;

πŸ’» The Core Code

Here are the essential code snippets for the main functionality.

1. Database Configuration (includes/config.php)

<?php
// Database configuration
$host = 'localhost';
$dbname = 'ecommerce_db';
$username = 'root'; // Default XAMPP username
$password = '';     // Default XAMPP password (empty)
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
} catch(PDOException $e) {
die("Connection failed: " . $e->getMessage());
}
// Start session for cart functionality
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
// Initialize cart if it doesn't exist
if (!isset($_SESSION['cart'])) {
$_SESSION['cart'] = [];
}
// Helper function to sanitize input
function sanitize($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
// Helper function to format currency
function formatCurrency($amount) {
return '$' . number_format($amount, 2);
}
// Get total items in cart
function getCartCount() {
return array_sum(array_column($_SESSION['cart'], 'quantity'));
}
// Get cart subtotal
function getCartSubtotal() {
$subtotal = 0;
foreach ($_SESSION['cart'] as $item) {
$subtotal += $item['price'] * $item['quantity'];
}
return $subtotal;
}
?>

2. Public Header (includes/header.php)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo $page_title ?? 'E-Commerce Store'; ?></title>
<link rel="stylesheet" href="assets/css/style.css">
</head>
<body>
<header>
<nav class="navbar">
<div class="container">
<a href="index.php" class="logo">MyStore</a>
<ul class="nav-links">
<li><a href="index.php">Home</a></li>
<li><a href="index.php?category=1">Electronics</a></li>
<li><a href="index.php?category=2">Clothing</a></li>
<li><a href="index.php?category=3">Books</a></li>
</ul>
<div class="cart-icon">
<a href="cart.php">
πŸ›’ Cart 
<span class="cart-count"><?php echo getCartCount(); ?></span>
</a>
</div>
</div>
</nav>
</header>
<main>

3. Public Footer (includes/footer.php)

    </main>
<footer>
<div class="container">
<p>&copy; 2023 MyStore. All rights reserved.</p>
</div>
</footer>
<script src="assets/js/script.js"></script>
</body>
</html>

4. Product Listing Page (index.php)

<?php
$page_title = 'Home - MyStore';
require_once 'includes/config.php';
require_once 'includes/header.php';
// Get category filter
$category_id = isset($_GET['category']) ? (int)$_GET['category'] : 0;
// Fetch categories for filter
$categories = $pdo->query("SELECT * FROM categories ORDER BY name")->fetchAll();
// Fetch products with optional category filter
if ($category_id > 0) {
$stmt = $pdo->prepare("SELECT p.*, c.name as category_name 
FROM products p 
LEFT JOIN categories c ON p.category_id = c.id 
WHERE p.category_id = ? 
ORDER BY p.created_at DESC");
$stmt->execute([$category_id]);
$products = $stmt->fetchAll();
} else {
$products = $pdo->query("SELECT p.*, c.name as category_name 
FROM products p 
LEFT JOIN categories c ON p.category_id = c.id 
ORDER BY p.created_at DESC")->fetchAll();
}
?>
<div class="container">
<div class="row">
<!-- Sidebar with categories -->
<aside class="sidebar">
<h3>Categories</h3>
<ul class="category-list">
<li><a href="index.php" class="<?php echo !$category_id ? 'active' : ''; ?>">All Products</a></li>
<?php foreach ($categories as $cat): ?>
<li>
<a href="index.php?category=<?php echo $cat['id']; ?>" 
class="<?php echo $category_id == $cat['id'] ? 'active' : ''; ?>">
<?php echo htmlspecialchars($cat['name']); ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</aside>
<!-- Main content - Product grid -->
<main class="main-content">
<h1>Our Products</h1>
<?php if (empty($products)): ?>
<p>No products found in this category.</p>
<?php else: ?>
<div class="product-grid">
<?php foreach ($products as $product): ?>
<div class="product-card">
<img src="assets/images/products/<?php echo htmlspecialchars($product['image']); ?>" 
alt="<?php echo htmlspecialchars($product['name']); ?>"
onerror="this.src='assets/images/placeholder.jpg'">
<h3><?php echo htmlspecialchars($product['name']); ?></h3>
<p class="price"><?php echo formatCurrency($product['price']); ?></p>
<p class="stock">Stock: <?php echo $product['stock']; ?></p>
<a href="product.php?id=<?php echo $product['id']; ?>" class="btn">View Details</a>
<button onclick="addToCart(<?php echo $product['id']; ?>, 1)" class="btn btn-primary">Add to Cart</button>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</main>
</div>
</div>
<script>
function addToCart(productId, quantity) {
fetch('cart-actions.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'action=add&product_id=' + productId + '&quantity=' + quantity
})
.then(response => response.json())
.then(data => {
if (data.success) {
// Update cart count in header
document.querySelector('.cart-count').textContent = data.cart_count;
alert('Product added to cart!');
}
});
}
</script>
<?php require_once 'includes/footer.php'; ?>

5. Cart Page (cart.php)

<?php
$page_title = 'Shopping Cart - MyStore';
require_once 'includes/config.php';
require_once 'includes/header.php';
// Handle quantity updates
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['update_cart'])) {
foreach ($_POST['quantity'] as $product_id => $quantity) {
if ($quantity <= 0) {
unset($_SESSION['cart'][$product_id]);
} else {
$_SESSION['cart'][$product_id]['quantity'] = (int)$quantity;
}
}
}
if (isset($_POST['remove_item'])) {
$product_id = $_POST['product_id'];
unset($_SESSION['cart'][$product_id]);
}
// Redirect to prevent form resubmission
header('Location: cart.php');
exit;
}
?>
<div class="container">
<h1>Shopping Cart</h1>
<?php if (empty($_SESSION['cart'])): ?>
<p>Your cart is empty. <a href="index.php">Continue shopping</a></p>
<?php else: ?>
<form method="POST" action="">
<table class="cart-table">
<thead>
<tr>
<th>Product</th>
<th>Price</th>
<th>Quantity</th>
<th>Subtotal</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php 
$total = 0;
foreach ($_SESSION['cart'] as $product_id => $item): 
$subtotal = $item['price'] * $item['quantity'];
$total += $subtotal;
?>
<tr>
<td>
<img src="assets/images/products/<?php echo htmlspecialchars($item['image']); ?>" 
alt="<?php echo htmlspecialchars($item['name']); ?>" 
width="50">
<?php echo htmlspecialchars($item['name']); ?>
</td>
<td><?php echo formatCurrency($item['price']); ?></td>
<td>
<input type="number" name="quantity[<?php echo $product_id; ?>]" 
value="<?php echo $item['quantity']; ?>" min="0" max="99" 
style="width: 60px;">
</td>
<td><?php echo formatCurrency($subtotal); ?></td>
<td>
<button type="submit" name="remove_item" value="1" 
onclick="this.form.product_id.value='<?php echo $product_id; ?>'">
Remove
</button>
<input type="hidden" name="product_id" value="">
</td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot>
<tr>
<td colspan="3" align="right"><strong>Total:</strong></td>
<td><strong><?php echo formatCurrency($total); ?></strong></td>
<td></td>
</tr>
</tfoot>
</table>
<div class="cart-actions">
<button type="submit" name="update_cart" class="btn">Update Cart</button>
<a href="checkout.php" class="btn btn-primary">Proceed to Checkout</a>
</div>
</form>
<?php endif; ?>
</div>
<?php require_once 'includes/footer.php'; ?>

6. Cart Actions AJAX Handler (cart-actions.php)

<?php
require_once 'includes/config.php';
header('Content-Type: application/json');
$action = $_POST['action'] ?? '';
switch ($action) {
case 'add':
$product_id = (int)$_POST['product_id'];
$quantity = (int)$_POST['quantity'];
// Fetch product details from database
$stmt = $pdo->prepare("SELECT id, name, price, image FROM products WHERE id = ?");
$stmt->execute([$product_id]);
$product = $stmt->fetch();
if ($product) {
if (isset($_SESSION['cart'][$product_id])) {
$_SESSION['cart'][$product_id]['quantity'] += $quantity;
} else {
$_SESSION['cart'][$product_id] = [
'name' => $product['name'],
'price' => $product['price'],
'image' => $product['image'],
'quantity' => $quantity
];
}
echo json_encode([
'success' => true,
'cart_count' => getCartCount(),
'message' => 'Product added to cart'
]);
} else {
echo json_encode(['success' => false, 'message' => 'Product not found']);
}
break;
case 'remove':
$product_id = (int)$_POST['product_id'];
unset($_SESSION['cart'][$product_id]);
echo json_encode([
'success' => true,
'cart_count' => getCartCount(),
'message' => 'Product removed from cart'
]);
break;
default:
echo json_encode(['success' => false, 'message' => 'Invalid action']);
}
?>

7. Checkout Page (checkout.php)

<?php
$page_title = 'Checkout - MyStore';
require_once 'includes/config.php';
// Redirect if cart is empty
if (empty($_SESSION['cart'])) {
header('Location: index.php');
exit;
}
$error = '';
$success = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = sanitize($_POST['name'] ?? '');
$email = sanitize($_POST['email'] ?? '');
$address = sanitize($_POST['address'] ?? '');
if (empty($name) || empty($email) || empty($address)) {
$error = 'Please fill in all fields';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$error = 'Please enter a valid email address';
} else {
try {
$pdo->beginTransaction();
// Calculate total
$total = getCartSubtotal();
// Insert order
$stmt = $pdo->prepare("INSERT INTO orders (customer_name, customer_email, customer_address, total_amount) 
VALUES (?, ?, ?, ?)");
$stmt->execute([$name, $email, $address, $total]);
$order_id = $pdo->lastInsertId();
// Insert order items
$stmt = $pdo->prepare("INSERT INTO order_items (order_id, product_id, product_name, quantity, price) 
VALUES (?, ?, ?, ?, ?)");
foreach ($_SESSION['cart'] as $product_id => $item) {
$stmt->execute([
$order_id,
$product_id,
$item['name'],
$item['quantity'],
$item['price']
]);
// Update stock (optional)
$updateStock = $pdo->prepare("UPDATE products SET stock = stock - ? WHERE id = ?");
$updateStock->execute([$item['quantity'], $product_id]);
}
$pdo->commit();
// Clear cart
$_SESSION['cart'] = [];
// Redirect to confirmation page
header("Location: order-confirmation.php?order_id=$order_id");
exit;
} catch (Exception $e) {
$pdo->rollBack();
$error = 'An error occurred. Please try again.';
}
}
}
require_once 'includes/header.php';
?>
<div class="container">
<h1>Checkout</h1>
<?php if ($error): ?>
<div class="alert alert-error"><?php echo $error; ?></div>
<?php endif; ?>
<div class="checkout-container">
<div class="checkout-form">
<h2>Customer Information</h2>
<form method="POST" action="">
<div class="form-group">
<label for="name">Full Name *</label>
<input type="text" id="name" name="name" required 
value="<?php echo htmlspecialchars($_POST['name'] ?? ''); ?>">
</div>
<div class="form-group">
<label for="email">Email *</label>
<input type="email" id="email" name="email" required 
value="<?php echo htmlspecialchars($_POST['email'] ?? ''); ?>">
</div>
<div class="form-group">
<label for="address">Shipping Address *</label>
<textarea id="address" name="address" rows="4" required><?php 
echo htmlspecialchars($_POST['address'] ?? ''); 
?></textarea>
</div>
<button type="submit" class="btn btn-primary btn-block">Place Order</button>
</form>
</div>
<div class="order-summary">
<h2>Order Summary</h2>
<table>
<?php foreach ($_SESSION['cart'] as $item): ?>
<tr>
<td><?php echo htmlspecialchars($item['name']); ?> x <?php echo $item['quantity']; ?></td>
<td><?php echo formatCurrency($item['price'] * $item['quantity']); ?></td>
</tr>
<?php endforeach; ?>
<tr class="total">
<td><strong>Total:</strong></td>
<td><strong><?php echo formatCurrency(getCartSubtotal()); ?></strong></td>
</tr>
</table>
</div>
</div>
</div>
<?php require_once 'includes/footer.php'; ?>

8. Admin Authentication (admin/index.php)

<?php
session_start();
// If already logged in, redirect to dashboard
if (isset($_SESSION['admin_loggedin']) && $_SESSION['admin_loggedin'] === true) {
header('Location: dashboard.php');
exit;
}
require_once '../includes/config.php';
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
$stmt = $pdo->prepare("SELECT id, username, password FROM admin WHERE username = ?");
$stmt->execute([$username]);
$admin = $stmt->fetch();
if ($admin && password_verify($password, $admin['password'])) {
$_SESSION['admin_loggedin'] = true;
$_SESSION['admin_id'] = $admin['id'];
$_SESSION['admin_username'] = $admin['username'];
header('Location: dashboard.php');
exit;
} else {
$error = 'Invalid username or password';
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Admin Login</title>
<link rel="stylesheet" href="css/admin-style.css">
</head>
<body class="login-page">
<div class="login-container">
<h1>Admin Login</h1>
<?php if ($error): ?>
<div class="alert alert-error"><?php echo $error; ?></div>
<?php endif; ?>
<form method="POST" action="">
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" name="username" required>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit" class="btn btn-primary btn-block">Login</button>
</form>
</div>
</body>
</html>

9. Admin Dashboard (admin/dashboard.php)

<?php
require_once '../includes/config.php';
require_once '../includes/auth.php';
// Get statistics
$totalProducts = $pdo->query("SELECT COUNT(*) FROM products")->fetchColumn();
$totalOrders = $pdo->query("SELECT COUNT(*) FROM orders")->fetchColumn();
$totalRevenue = $pdo->query("SELECT SUM(total_amount) FROM orders WHERE status != 'cancelled'")->fetchColumn();
$recentOrders = $pdo->query("SELECT * FROM orders ORDER BY created_at DESC LIMIT 5")->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Admin Dashboard</title>
<link rel="stylesheet" href="css/admin-style.css">
</head>
<body>
<div class="admin-container">
<?php include 'includes/sidebar.php'; ?>
<main class="admin-main">
<h1>Dashboard</h1>
<div class="stats-grid">
<div class="stat-card">
<h3>Total Products</h3>
<p class="stat-number"><?php echo $totalProducts; ?></p>
</div>
<div class="stat-card">
<h3>Total Orders</h3>
<p class="stat-number"><?php echo $totalOrders; ?></p>
</div>
<div class="stat-card">
<h3>Total Revenue</h3>
<p class="stat-number"><?php echo formatCurrency($totalRevenue ?? 0); ?></p>
</div>
</div>
<h2>Recent Orders</h2>
<table class="data-table">
<thead>
<tr>
<th>Order ID</th>
<th>Customer</th>
<th>Total</th>
<th>Status</th>
<th>Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($recentOrders as $order): ?>
<tr>
<td>#<?php echo $order['id']; ?></td>
<td><?php echo htmlspecialchars($order['customer_name']); ?></td>
<td><?php echo formatCurrency($order['total_amount']); ?></td>
<td>
<span class="status status-<?php echo $order['status']; ?>">
<?php echo $order['status']; ?>
</span>
</td>
<td><?php echo date('M d, Y', strtotime($order['created_at'])); ?></td>
<td>
<a href="order-details.php?id=<?php echo $order['id']; ?>" class="btn-small">View</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</main>
</div>
</body>
</html>

10. CSS Styling (assets/css/style.css)

/* Reset and Base Styles */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
/* Navigation */
.navbar {
background: #333;
color: #fff;
padding: 1rem 0;
}
.navbar .container {
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
color: #fff;
text-decoration: none;
font-size: 1.5rem;
font-weight: bold;
}
.nav-links {
list-style: none;
display: flex;
}
.nav-links li {
margin-left: 20px;
}
.nav-links a {
color: #fff;
text-decoration: none;
}
.nav-links a:hover {
color: #ff6b6b;
}
.cart-icon a {
color: #fff;
text-decoration: none;
padding: 5px 10px;
background: #ff6b6b;
border-radius: 4px;
}
.cart-count {
background: #fff;
color: #333;
padding: 2px 6px;
border-radius: 50%;
font-size: 0.8rem;
margin-left: 5px;
}
/* Layout */
.row {
display: flex;
gap: 30px;
margin-top: 30px;
}
.sidebar {
flex: 1;
background: #f4f4f4;
padding: 20px;
border-radius: 8px;
}
.main-content {
flex: 3;
}
/* Category List */
.category-list {
list-style: none;
margin-top: 15px;
}
.category-list li {
margin-bottom: 10px;
}
.category-list a {
color: #333;
text-decoration: none;
display: block;
padding: 5px 10px;
border-radius: 4px;
}
.category-list a:hover,
.category-list a.active {
background: #ff6b6b;
color: #fff;
}
/* Product Grid */
.product-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
margin-top: 20px;
}
.product-card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 15px;
text-align: center;
}
.product-card img {
max-width: 100%;
height: 200px;
object-fit: cover;
border-radius: 4px;
margin-bottom: 10px;
}
.product-card h3 {
margin-bottom: 10px;
}
.price {
font-size: 1.2rem;
font-weight: bold;
color: #ff6b6b;
margin-bottom: 10px;
}
.stock {
color: #666;
margin-bottom: 15px;
}
.btn {
display: inline-block;
padding: 8px 16px;
background: #f4f4f4;
color: #333;
text-decoration: none;
border: none;
border-radius: 4px;
cursor: pointer;
margin: 2px;
}
.btn-primary {
background: #ff6b6b;
color: #fff;
}
.btn-block {
display: block;
width: 100%;
}
/* Cart Table */
.cart-table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.cart-table th,
.cart-table td {
padding: 10px;
text-align: left;
border-bottom: 1px solid #ddd;
}
.cart-table th {
background: #f4f4f4;
}
.cart-actions {
margin-top: 20px;
display: flex;
gap: 10px;
justify-content: flex-end;
}
/* Checkout */
.checkout-container {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 30px;
margin-top: 20px;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.form-group input,
.form-group textarea {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
.order-summary {
background: #f4f4f4;
padding: 20px;
border-radius: 8px;
}
.order-summary table {
width: 100%;
margin-top: 15px;
}
.order-summary td {
padding: 10px 0;
}
.order-summary .total {
border-top: 2px solid #ddd;
font-size: 1.2rem;
}
/* Alerts */
.alert {
padding: 10px 15px;
border-radius: 4px;
margin-bottom: 20px;
}
.alert-error {
background: #ffe6e6;
color: #cc0000;
border: 1px solid #ff9999;
}
/* Footer */
footer {
background: #333;
color: #fff;
text-align: center;
padding: 20px 0;
margin-top: 40px;
}
/* Responsive */
@media (max-width: 768px) {
.row {
flex-direction: column;
}
.checkout-container {
grid-template-columns: 1fr;
}
.nav-links {
display: none;
}
}

πŸ“ How to Use This Project (Step-by-Step Guide)

Step 1: Install Local Server

  • Download and install XAMPP from apachefriends.org
  • Install and launch XAMPP Control Panel
  • Start Apache and MySQL services

Step 2: Create Project Folder

  • Navigate to C:\xampp\htdocs\ (Windows) or /Applications/XAMPP/htdocs/ (Mac)
  • Create a new folder named ecommerce-basic

Step 3: Set Up Database

  • Open browser and go to http://localhost/phpmyadmin
  • Click on "SQL" tab
  • Copy the entire SQL from database/ecommerce.sql above
  • Paste and click "Go" to create database and tables

Step 4: Create Admin Password Hash

  1. Create a file named hash.php in your project root:
<?php
echo password_hash('admin123', PASSWORD_DEFAULT);
?>
  1. Run it: http://localhost/ecommerce-basic/hash.php
  2. Copy the output (long hash string)
  3. In phpMyAdmin, open admin table
  4. Replace the password field value with your copied hash
  5. Delete hash.php after done

Step 5: Add Product Images

  • Download some sample product images
  • Place them in assets/images/products/
  • Make sure filenames match those in database (headphones.jpg, smartwatch.jpg, etc.)

Step 6: Configure Database Connection

  • Open includes/config.php
  • Verify database credentials:
$host = 'localhost';
$dbname = 'ecommerce_db';
$username = 'root';  // Default XAMPP username
$password = '';      // Default XAMPP password (empty)

Step 7: Test the Website

Customer Side:

  • Open: http://localhost/ecommerce-basic/
  • Browse products
  • Add items to cart
  • View cart and update quantities
  • Proceed to checkout

Admin Side:

  • Open: http://localhost/ecommerce-basic/admin/
  • Login with: Username: admin, Password: admin123
  • View dashboard
  • Manage products (add/edit/delete)
  • View orders

Step 8: Add Sample Products via Admin

  1. Log in to admin panel
  2. Go to "Products" β†’ "Add New"
  3. Fill in product details:
  • Name: "Gaming Mouse"
  • Category: Electronics
  • Price: 49.99
  • Description: "High-precision gaming mouse with RGB lighting"
  • Stock: 30
  • Image: Upload an image

Step 9: Customize the Store

  • Edit includes/header.php to change store name
  • Modify assets/css/style.css to change colors and styling
  • Add more categories in admin panel
  • Add payment gateway integration (optional)

Step 10: Deploy to Live Server

  1. Upload all files to your web hosting
  2. Create MySQL database on hosting
  3. Import the SQL file
  4. Update includes/config.php with live database credentials
  5. Generate new password hash on live server
  6. Update file permissions for image uploads

🎯 Features Summary

Customer Features:

  • βœ… Browse products by category
  • βœ… View product details
  • βœ… Add to cart with AJAX
  • βœ… Update cart quantities
  • βœ… Remove items from cart
  • βœ… Checkout form
  • βœ… Order confirmation
  • βœ… Responsive design

Admin Features:

  • βœ… Secure login
  • βœ… Dashboard with statistics
  • βœ… Add new products
  • βœ… Edit existing products
  • βœ… Delete products
  • βœ… Manage categories
  • βœ… View all orders
  • βœ… Update order status
  • βœ… Product image upload

Database Features:

  • βœ… Products table with categories
  • βœ… Orders and order items tracking
  • βœ… Stock management
  • βœ… Admin authentication
  • βœ… Foreign key relationships

πŸš€ Future Enhancements Ideas

  1. User Accounts: Allow customers to create accounts and view order history
  2. Payment Integration: Add Stripe or PayPal payment gateway
  3. Product Search: Add search functionality
  4. Product Reviews: Let customers leave reviews
  5. Email Notifications: Send order confirmation emails
  6. Discount Codes: Add coupon/promo code system
  7. Product Variants: Support sizes, colors, etc.
  8. Wishlist: Let customers save items for later
  9. Related Products: Show related items on product page
  10. Inventory Alerts: Notify admin when stock is low

This basic e-commerce website provides a solid foundation that you can build upon and customize according to your specific needs!

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper