Module 4: Product & Category Management

Let's manage what we sell. This module covers the essential CRUD operations for products and categories.

The Heart of the System: CRUD Operations

With our authentication system in place, it's time to build the core features of the bakery management system. This starts with managing our products and their categories. To do this, we will implement **CRUD** functionality:

  • Create: Add new categories and products to the database.
  • Read: Display a list of all existing categories and products.
  • Update: Edit the details of an existing item.
  • Delete: Remove an item from the database.

These four operations are the building blocks for most dynamic web applications.

Step 1: Managing Categories

We'll start with the simpler of the two: categories. We need a page where an admin can add, view, and delete product categories. Create a file named `manage_categories.php` inside the `admin/` folder.

This single file will handle everything: displaying the form, processing the form submission to add a new category, and listing all current categories from the database.

admin/manage_categories.php
<?php
session_start();
require_once '../includes/db.php';

// Check if user is logged in and is an admin
if (!isset($_SESSION["loggedin"]) || $_SESSION["role"] !== 'admin') {
    header("location: ../login.php");
    exit;
}

// Handle form submission for adding a new category
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['add_category'])) {
    $name = trim($_POST['name']);
    $description = trim($_POST['description']);

    $sql = "INSERT INTO categories (name, description) VALUES (?, ?)";
    if ($stmt = $conn->prepare($sql)) {
        $stmt->bind_param("ss", $name, $description);
        $stmt->execute();
        $stmt->close();
    }
}

// Fetch all categories
$categories = $conn->query("SELECT * FROM categories ORDER BY name ASC");
?>

<!-- HTML to display the form and list -->
<h2>Manage Categories</h2>

<!-- Form to Add Category -->
<form action="manage_categories.php" method="post">
    <input type="text" name="name" placeholder="Category Name" required>
    <textarea name="description" placeholder="Description"></textarea>
    <button type="submit" name="add_category">Add Category</button>
</form>

<!-- Table to List Categories -->
<table border="1">
    <tr>
        <th>Name</th>
        <th>Description</th>
        <th>Actions</th>
    </tr>
    <?php while ($row = $categories->fetch_assoc()): ?>
    <tr>
        <td><?php echo htmlspecialchars($row['name']); ?></td>
        <td><?php echo htmlspecialchars($row['description']); ?></td>
        <td>
            <!-- Links for edit/delete functionality (to be built) -->
            <a href="edit_category.php?id=<?php echo $row['id']; ?>">Edit</a>
            <a href="delete_category.php?id=<?php echo $row['id']; ?>" onclick="return confirm('Are you sure?')">Delete</a>
        </td>
    </tr>
    <?php endwhile; ?>
</table>
                            

Step 2: Managing Products with Image Uploads

Managing products is more complex because it involves a relationship with the `categories` table and includes handling file uploads for product images. Create a file named `manage_products.php` in the `admin/` directory.

Handling File Uploads: When a form with `enctype="multipart/form-data"` is submitted, PHP stores the uploaded file in a temporary location. Our script needs to validate the file (e.g., check its size and type) and then move it to a permanent directory on our server, such as `assets/images/`. We store the path to the image in the database, not the image itself.

admin/manage_products.php
<?php
session_start();
require_once '../includes/db.php';

// Check if user is logged in
if (!isset($_SESSION["loggedin"])) {
    header("location: ../login.php");
    exit;
}

// Handle adding a new product
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['add_product'])) {
    $name = $_POST['name'];
    $category_id = $_POST['category_id'];
    $price = $_POST['price'];
    $stock = $_POST['stock'];
    $description = $_POST['description'];
    
    // Image upload logic
    $target_dir = "../assets/images/";
    $image_name = basename($_FILES["image"]["name"]);
    $target_file = $target_dir . $image_name;
    $image_url = "assets/images/" . $image_name;
    
    // Move the uploaded file to the target directory
    if (move_uploaded_file($_FILES["image"]["tmp_name"], $target_file)) {
        $sql = "INSERT INTO products (name, category_id, price, stock, description, image_url) VALUES (?, ?, ?, ?, ?, ?)";
        if ($stmt = $conn->prepare($sql)) {
            $stmt->bind_param("sidis", $name, $category_id, $price, $stock, $description, $image_url);
            $stmt->execute();
        }
    } else {
        echo "Error uploading file.";
    }
}

// Fetch all products with category names
$products = $conn->query("SELECT p.*, c.name AS category_name FROM products p JOIN categories c ON p.category_id = c.id ORDER BY p.name ASC");

// Fetch categories for the dropdown
$categories = $conn->query("SELECT * FROM categories ORDER BY name ASC");
?>
<!-- HTML Form and Table -->
<h2>Manage Products</h2>
<!-- The form needs enctype for file uploads -->
<form action="manage_products.php" method="post" enctype="multipart/form-data">
    <select name="category_id" required>
        <?php while ($cat = $categories->fetch_assoc()): ?>
            <option value="<?php echo $cat['id']; ?>"><?php echo htmlspecialchars($cat['name']); ?></option>
        <?php endwhile; ?>
    </select>
    <input type="text" name="name" placeholder="Product Name" required>
    <input type="number" step="0.01" name="price" placeholder="Price" required>
    <input type="number" name="stock" placeholder="Stock" required>
    <textarea name="description" placeholder="Description"></textarea>
    <input type="file" name="image" required>
    <button type="submit" name="add_product">Add Product</button>
</form>

<!-- Table to display products -->
<!-- Similar table structure to categories, displaying product info -->