You have already learned how to build a dashboard layout with header.php, footer.php, and sidebar.php inside an include folder. Now it’s time to put that layout to real use. In this tutorial, we will build a complete PHP Product CRUD system — a real feature you will find inside almost every admin panel, from small shops to large e-commerce platforms.

This is Tutorial 11 of 13 in our PHP Advanced series. This is a hands-on, practical project tutorial. You will build Add, List, Edit, and Delete functionality for a Product module, step by step, using plain mysqli functions — no prepared statements, so the code stays simple and easy to follow at your current level. Build every file exactly as shown, test it as you go, and by the end you will have a fully working PHP Product CRUD module inside your dashboard.

What You Will Build

By the end of this PHP Product CRUD tutorial, your dashboard will be able to add a new product, show all products in a table, edit an existing product, and delete a product — all connected to a real MySQL database, using the same header, footer, and sidebar layout you already built.

Step 1: Create the Database and Products Table

Open phpMyAdmin from your XAMPP control panel and create a new database. You can name it anything, for example dashboard_db. Once created, click on the SQL tab and paste this code to create your products table.

CREATE TABLE products (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(150),
    details TEXT,
    regprice DECIMAL(10,2),
    saleprice DECIMAL(10,2),
    pdt DATE,
    udt DATE NULL,
    picture VARCHAR(255),
    active VARCHAR(10)
);

Let’s understand each column of this PHP Product CRUD table before moving forward:

  • id — a unique number for every product, generated automatically
  • name — the product name
  • details — product description
  • regprice — regular price
  • saleprice — sale/discounted price
  • pdt — the date the product was added (production date)
  • udt — the date the product was last updated
  • picture — the filename of the product image
  • active — stores “yes” or “no” to control whether the product is visible or hidden

Run this SQL once, and your products table is ready to store real data.

Step 2: Create connection.php Inside the Include Folder

Inside your existing include folder — the same one holding header.php, footer.php, and sidebar.php — create a new file called connection.php.

<?php
define('Host','localhost');
define('userName','root');
define('password','');
define('DBNAME','dashboard_db');

$connection = mysqli_connect(Host,userName,password,DBNAME);
?>

Let’s understand what is happening here. The define() function creates a constant — a named value that never changes anywhere else in your script once it’s set. Instead of typing “localhost” directly every time, we store it once inside Host, and PHP will replace Host with “localhost” wherever it appears.

We do the same for userName, password, and DBNAME. This keeps all your database settings in one clean, organized place. Finally, mysqli_connect() takes these four constants and creates the actual PHP Product CRUD database connection, storing it inside the $connection variable, which every other file will use to talk to the database.

Step 3: Include connection.php on Every Page

Every single page in this PHP Product CRUD module needs access to $connection. So at the very top of add_product.php, product.php, edit.php, update.php, and delete.php, add this line first, before any other code.

<?php
include 'include/connection.php';
?>

This single line gives every page instant access to your database connection, without repeating the mysqli_connect() code again and again. This is exactly the same include pattern you already practiced with header.php and footer.php.

Step 4: Create add_product.php — Insert a New Product

Now let’s build the Add step of our PHP Product CRUD system. Create a file called add_product.php. First, place this PHP code at the very top of the page, above your HTML.

<?php
include 'include/connection.php';

$tableName = "products";
$pageName = "product.php";

if(isset($_POST['Insert'])){
    $name     = $_POST['name'];
    $detail   = $_POST['detail'];
    $pic      = $_POST['image'];
    $pdt      = date('Y-m-d');
    $rprice   = $_POST['rprice'];
    $sprice   = $_POST['sprice'];
    $active   = $_POST['active'];

    $addQuery = "insert into $tableName (name, details, regprice, saleprice, pdt, picture, active) 
                 values ('$name','$detail','$rprice','$sprice','$pdt','$pic','$active')";

    mysqli_query($connection, $addQuery);

    header("location:$pageName");
    exit;
}
?>

Let’s break this down step by step. The $tableName and $pageName variables store the table name and the page we redirect to after saving — this way, if you ever rename your table or page, you only change it in one place.

The isset($_POST['Insert']) check confirms the form was actually submitted before running any database code. Then we collect every form field into simple variables — $name, $detail, $rprice, and so on. The date('Y-m-d') function automatically generates today’s date for the pdt column, so you never need to type it manually.

Finally, mysqli_query() runs the insert command against your database, and header("location:$pageName") redirects the admin straight to the product list page after saving — a smooth flow for anyone managing your PHP Product CRUD dashboard.

Now add the HTML form below that PHP code, inside your dashboard layout.

<?php include 'include/header.php'; ?>
<?php include 'include/sidebar.php'; ?>

<div class="content">
<h2>Add New Product</h2>

<form method="POST">
    Product Name: <input type="text" name="name" required><br>
    Details: <textarea name="detail" required></textarea><br>
    Image Filename: <input type="text" name="image"><br>
    Regular Price: <input type="number" step="0.01" name="rprice" required><br>
    Sale Price: <input type="number" step="0.01" name="sprice" required><br>
    Active:
    <select name="active">
        <option value="yes">Yes</option>
        <option value="no">No</option>
    </select><br>
    <input type="submit" name="Insert" value="Add Product">
</form>
</div>

<?php include 'include/footer.php'; ?>

Notice how the form sits neatly between your header, sidebar, and footer includes — this is exactly the dashboard structure you already built, now doing real work with a PHP Product CRUD form inside it.

Step 5: Create product.php — List All Products

Now let’s display every saved product in a table. Create product.php, starting with the PHP code at the top.

<?php
include 'include/connection.php';

$tableName = "products";
$pageName = "product.php";

$showQuery = "select * from $tableName order by id desc";
$result = mysqli_query($connection, $showQuery);
?>

The query selects every row from the products table, ordering the newest products first. mysqli_query() runs it and stores the result set inside $result, ready for us to loop through in the HTML below.

<?php include 'include/header.php'; ?>
<?php include 'include/sidebar.php'; ?>

<div class="content">
<h2>All Products</h2>

<a href="add_product.php">+ Add New Product</a>

<table border="1" cellpadding="8">
<tr>
    <th>ID</th>
    <th>Name</th>
    <th>Details</th>
    <th>Added Date</th>
    <th>Updated Date</th>
    <th>Actions</th>
</tr>

<?php
if(mysqli_num_rows($result) > 0){
    while($row = mysqli_fetch_assoc($result)){
?>
<tr>
    <td><?php echo $row['id']; ?></td>
    <td>
        <?php echo $row['name']; ?><br>
        <?php if(!empty($row['picture'])){ ?>
            <img src="../products/<?php echo $row['picture']; ?>" width="120" height="90">
        <?php } ?>
    </td>
    <td>
        <?php echo $row['details']; ?><br>
        Regular Price: $<?php echo $row['regprice']; ?>/-<br>
        Sale Price: $<?php echo $row['saleprice']; ?>/-
    </td>
    <td><?php echo $row['pdt']; ?></td>
    <td><?php echo $row['udt']; ?></td>
    <td>
        <a href="edit.php?id=<?php echo $row['id']; ?>">Edit</a>
        <a href="delete.php?did=<?php echo $row['id']; ?>" onclick="return confirm('Are you sure you want to delete this product?')">Delete</a>

        <?php if($row['active'] == 'no'){ ?>
            <a href="<?php echo $pageName; ?>?eid=<?php echo $row['id']; ?>&active=yes">Activate</a>
        <?php } else { ?>
            <a href="<?php echo $pageName; ?>?eid=<?php echo $row['id']; ?>&active=no">Deactivate</a>
        <?php } ?>
    </td>
</tr>
<?php
    }
} else {
?>
<tr>
    <td colspan="6">
        <h2>Record Not Found</h2>
    </td>
</tr>
<?php } ?>

</table>
</div>

<?php include 'include/footer.php'; ?>

Walk through the logic here carefully. mysqli_num_rows($result) checks how many rows the query returned. If it’s more than zero, the while loop runs, and mysqli_fetch_assoc() pulls one product at a time as an associative array, letting us print each column using $row['column_name']. If no products exist yet, the else block shows a friendly “Record Not Found” message instead of an empty table — good practice in any PHP Product CRUD listing page.

Step 6: Create edit.php — Retrieve Product Data for Editing

Before we can update a product, we first need to pull its existing data into a form. Create edit.php, starting with this PHP code at the top.

<?php
include 'include/connection.php';

$tableName = "products";

if(isset($_GET['id'])){
    $editId = $_GET['id'];

    $getQuery = "select * from $tableName where id='$editId'";
    $getData = mysqli_query($connection, $getQuery);
    $data = mysqli_fetch_assoc($getData);
}
?>

When you click the “Edit” link from product.php, it sends the product’s id through the URL using $_GET['id']. We use that id inside a SELECT query to fetch that one specific product’s data, then mysqli_fetch_assoc() converts it into the $data array, ready to pre-fill our edit form in the next step.

Step 7: Build the Edit Form and Show Retrieved Data

Now let’s display that retrieved data inside an HTML form, so the admin can see the current values and change whatever is needed.

<?php include 'include/header.php'; ?>
<?php include 'include/sidebar.php'; ?>

<div class="content">
<h2>Edit Product</h2>

<form method="POST" action="update.php">
    <input type="hidden" name="hdn" value="<?php echo $data['id']; ?>">

    Product Name: <input type="text" name="name" value="<?php echo $data['name']; ?>" required><br>
    Details: <textarea name="detail" required><?php echo $data['details']; ?></textarea><br>
    Image Filename: <input type="text" name="picture" value="<?php echo $data['picture']; ?>"><br>
    Regular Price: <input type="number" step="0.01" name="rprice" value="<?php echo $data['regprice']; ?>" required><br>
    Sale Price: <input type="number" step="0.01" name="sprice" value="<?php echo $data['saleprice']; ?>" required><br>
    Active:
    <select name="active">
        <option value="yes" <?php if($data['active']=='yes') echo 'selected'; ?>>Yes</option>
        <option value="no" <?php if($data['active']=='no') echo 'selected'; ?>>No</option>
    </select><br>

    <input type="submit" name="Update" value="Update Product">
</form>
</div>

<?php include 'include/footer.php'; ?>

Notice the hidden input field named hdn — this silently carries the product’s id along with the form submission, without the admin needing to see or type it. Every visible field is pre-filled using $data['column_name'], so the admin immediately sees the current product information instead of a blank form. The dropdown uses a small inline check to automatically select “Yes” or “No” based on the product’s current active status.

Step 8: Create update.php — Save the Updated Product

Now let’s process the form submitted from edit.php. Create update.php.

<?php
include 'include/connection.php';

$tableName = "products";
$pageName = "product.php";

if(isset($_POST['Update'])){
    $hdn      = $_POST['hdn'];

    $name     = $_POST['name'];
    $detail   = $_POST['detail'];
    $pic      = $_POST['picture'];
    $udt      = date('Y-m-d');
    $rprice   = $_POST['rprice'];
    $sprice   = $_POST['sprice'];
    $active   = $_POST['active'];

    $updateQuery = "update $tableName set 
                     name='$name', 
                     details='$detail', 
                     regprice='$rprice', 
                     saleprice='$sprice', 
                     udt='$udt', 
                     picture='$pic', 
                     active='$active' 
                     where id='$hdn'";

    mysqli_query($connection, $updateQuery);

    header("location:$pageName");
    exit;
}
?>

This works almost identically to add_product.php, with one key difference — instead of an INSERT query, we use an UPDATE query, and we target the exact row using where id='$hdn', matching the hidden id field we carried over from the edit form. The $udt variable automatically records today’s date as the “last updated” date, giving you a clear history of when each product was last changed.

Step 9: Create delete.php — Remove a Product

Finally, let’s build the Delete step of our PHP Product CRUD system.

<?php
include 'include/connection.php';

$tableName = "products";
$pageName = "product.php";

if(isset($_GET['did'])){
    $did = $_GET['did'];

    $deleteQuery = "delete from $tableName where id='$did'";
    mysqli_query($connection, $deleteQuery);

    header("location:$pageName");
    exit;
}
?>

When the admin clicks “Delete” on product.php, the product’s id travels through the URL as $_GET['did']. We use it inside a DELETE query to remove that exact row from the products table, then redirect back to the product list — the same reliable pattern used across every step of this PHP Product CRUD module.

Handling the Activate / Deactivate Links

You may have noticed the Activate and Deactivate links inside product.php’s table. To make those work, add this small block at the very top of product.php, right after your connection include.

<?php
if(isset($_GET['eid']) && isset($_GET['active'])){
    $eid = $_GET['eid'];
    $activeStatus = $_GET['active'];

    $toggleQuery = "update $tableName set active='$activeStatus' where id='$eid'";
    mysqli_query($connection, $toggleQuery);

    header("location:$pageName");
    exit;
}
?>

This checks for both eid and active in the URL, then runs a quick UPDATE query to flip that specific product’s status, keeping your PHP Product CRUD dashboard fully interactive without needing a separate page for this small action.

Your Complete File Structure

By the end of this tutorial, your PHP Product CRUD project folder should look like this:

/include
    header.php
    footer.php
    sidebar.php
    connection.php

add_product.php
product.php
edit.php
update.php
delete.php

Every page except connection.php includes the header, sidebar, and footer, giving your entire Product module a consistent, professional dashboard look — exactly matching the layout you already taught your students. For official reference on the mysqli functions used throughout this tutorial, visit the official PHP MySQLi manual.

What’s Next?

You have now built a complete, working PHP Product CRUD system — Add, List, Edit, Delete, and Activate/Deactivate — inside a real dashboard layout using header, footer, and sidebar includes. In the next tutorial, we will explore Composer, the tool that manages external libraries and autoloading automatically in almost every modern PHP project.

If you missed the previous lesson, check out Tutorial 10: PHP Login System Guide, or explore all lessons in our PHP category.

Practice Exercise

Complete the following tasks to reinforce what you learned in this tutorial. Build every file yourself, exactly following the steps above, and test each action inside your dashboard.

  • Create the products table using the SQL provided in Step 1
  • Build connection.php inside your include folder, matching Step 2
  • Build add_product.php and successfully add three different products
  • Build product.php and confirm all three products display correctly in the table
  • Click Edit on one product, confirm the form loads with its existing data pre-filled
  • Update that product’s price and details, then confirm the changes reflect correctly in the product list
  • Delete one product using the Delete link, and confirm it disappears from the list immediately
  • Click Deactivate on a product, then Activate it again, confirming the status updates correctly both times

Bonus Challenge: Add a search box at the top of product.php that lets the admin search products by name using $_GET, filtering the table to show only matching results without affecting the Add, Edit, or Delete functionality.

About Author

Arshad Sultan

Arshad Sultan is the Founder of Tutorials Ocean and a Technical Architect & Full-Stack Developer with 15+ years of experience in PHP, Laravel, CRM development, API integrations, and AI-powered automation. He also runs Rapid Code, a software and AI automation agency, and has trained hundreds of students across Karachi's IT institutes since 2010.

Leave a Reply

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