PHP CRUD with Live Input Data Duplicate Validation Tutorial

In this tutorial, we will tackle about creating a Simple Web Application with CRUD Operation and preventing duplication input value. We will be using PHP Language as the back-end and MySQL Database. The Duplication Validation that we'll be creating, is a real-time or live function using jQuery, and by using Ajax Request, data validation will be automatically triggers without leaving the page or submitting the form yet.

In the simple application that we will be creating, I will use Bootstrap v5 as the CSS Framework and jQuery to execute our Ajax Requests.

The goal of the application that we'll create is a simple Product Listing that have a CRUD (Create, Read, Edit, and Delete) Operation and Duplicate Validation for the code field. The Code Field will serve as unique code of the products.

Getting Started:

Download and Install any local web servers that has an Apache WebServer and MySQL Database Server such as XAMPP.

Download and Compile the following libraries in your source code folder.

Before you continue below, please make sure that your Apache and MySQL is already running in your system.

Creating the Database

Open your PHPMyAdmin in a browser and create a new database naming dummy_db. Next, navigate to the SQL Tab/Page in your newly created database. Copy the SQL Script below and paste in the provided text field.

  1. CREATE TABLE `product_list` (
  2.   `code` varchar(50) DEFAULT NULL,
  3.   `product_name` varchar(50) DEFAULT NULL,
  4.   `description` text DEFAULT NULL,
  5.   `price` decimal(6,2) DEFAULT NULL

Creating the Database Connection

Open your favorite text-editor such as notepad++ or sublime text editors. Create a new PHP File naming db_connect.php and copy/paste the PHP Script Below. Save the file in your source code folder where your downloaded libraries are compiled.

  1. <?php
  2. // Database Host
  3. $host = 'localhost';
  4. // Database Username
  5. $username = 'root';
  6. // Database Password
  7. $password = '';
  8. // Selected Database Name
  9. $dbName = 'dummy_db';
  10.  
  11. $conn= new mysqli($host, $username, $password,$dbName);
  12. if(!$conn){
  13.     die("Database Connection Error: ".$conn->error);
  14. }

Creating the Interfaces

Next, we will be creating the user interfaces. Save the following files using the filename provided before each scripts.

index.php

This is the file which contains our main template of the application.

  1. <?php
  2. session_start();
  3. require_once('db_connect.php');
  4. $page = isset($_GET['page']) ? $_GET['page'] : 'home';
  5. ?>
  6. <!DOCTYPE html>
  7. <html lang="en">
  8.     <meta charset="UTF-8">
  9.     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  10.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  11.     <title><?php echo ucwords(str_replace('_',' ',$page)) ?></title>
  12.     <link rel="stylesheet" href="Font-Awesome-master/css/all.min.css">
  13.     <link rel="stylesheet" href="css/bootstrap.min.css">
  14.     <link rel="stylesheet" href="./css/custom.css">
  15.     <script src="js/jquery-3.6.0.min.js"></script>
  16.     <script src="js/bootstrap.min.js"></script>
  17.     <script src="js/script.js"></script>
  18.     <style>
  19.     </style>
  20. </head>
  21.     <main>
  22.     <nav class="navbar navbar-expand-lg navbar-dark bg-dark bg-gradient" id="topNavBar">
  23.         <div class="container">
  24.             <a class="navbar-brand fw-bolder" href="https://sourcecodester.com">
  25.             SourceCodester
  26.             </a>
  27.             <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
  28.             <span class="navbar-toggler-icon"></span>
  29.             </button>
  30.             <div class="collapse navbar-collapse" id="navbarNav">
  31.                 <ul class="navbar-nav">
  32.                     <li class="nav-item">
  33.                         <a class="nav-link <?php echo $page == "home" ? "active" :"" ?>" href="./?page=home">Home</a>
  34.                     </li>
  35.                     <li class="nav-item">
  36.                         <a class="nav-link <?php echo $page == "product_list" ? "active" :"" ?>" href="./?page=product_list">Product List</a>
  37.                     </li>
  38.                 </ul>
  39.             </div>
  40.             <div>
  41.                 <!-- <a href="./admin" id="login-btn" class="text-decoration-none text-light fw-bolder">Admin Panel</a> -->
  42.             </div>
  43.         </div>
  44.     </nav>
  45.     <div class="container py-3" id="page-container">
  46.         <?php
  47.            if(isset($_SESSION['flashdata'])):
  48.        ?>
  49.         <div class="dynamic_alert alert alert-<?php echo $_SESSION['flashdata']['type'] ?>">
  50.         <div class="float-end"><a href="javascript:void(0)" class="text-dark text-decoration-none" onclick="$(this).closest('.dynamic_alert').hide('slow').remove()">x</a></div>
  51.             <?php echo $_SESSION['flashdata']['msg'] ?>
  52.         </div>
  53.         <?php unset($_SESSION['flashdata']) ?>
  54.         <?php endif; ?>
  55.         <div class="content py-5">
  56.             <?php
  57.                include $page.'.php';
  58.            ?>
  59.         </div>
  60.     </div>
  61.     </main>
  62.  
  63. </body>
  64. </html>
  65. <?php if(isset($conn)) $conn->close(); ?>

home.php

This is the default page of the application when browsing the project. This contains the Add New Product Form.

  1. <div class="content py-3">
  2.     <h3 class="text-center fw-bolder">Add New Product</h3>
  3.     <center><hr class="bg-primary mx-1 opacity-100" style="width:5em"></center>
  4.     <div class="row justify-content-center">
  5.         <div class="card shadow col-md-8">
  6.             <div class="card-body">
  7.                 <div class="container-fluid py3">
  8.                     <form action="save_product.php" method="POST">
  9.                         <div class="row">
  10.                             <div class="col-md-12 form-group">
  11.                                 <label for="code" class="control-label text-primary">Code</label>
  12.                                 <input type="text" max="50" name="code" id="code" autofocus class="form-control form-control-sm" required>
  13.                             </div>
  14.                         </div>
  15.                         <div class="row">
  16.                             <div class="col-md-12 form-group">
  17.                                 <label for="product_name" class="control-label text-primary">Product Name</label>
  18.                                 <input type="text" name="product_name" id="product_name" class="form-control form-control-sm" required>
  19.                             </div>
  20.                         </div>
  21.                         <div class="row">
  22.                             <div class="col-md-12 form-group">
  23.                                 <label for="description" class="control-label text-primary">Description</label>
  24.                                 <textarea rows="3" name="description" id="description" class="form-control form-control-sm" required></textarea>
  25.                             </div>
  26.                         </div>
  27.                         <div class="row">
  28.                             <div class="col-md-12 form-group">
  29.                                 <label for="price" class="control-label text-primary">Price</label>
  30.                                 <input type="number" name="price" id="price" class="form-control form-control-sm text-end" required>
  31.                             </div>
  32.                         </div>
  33.                         <div class="row">
  34.                             <div class="form-group col-md-12 text-center mt-4">
  35.                                 <button class="btn btn-primary rounded-0 col-3" id="submit">Save</button>
  36.                                 <button class="btn btn-secondary rounded-0 col-3" type="reset">Cancel</button>
  37.                             </div>
  38.                         </div>
  39.                     </form>
  40.                 </div>
  41.             </div>
  42.         </div>
  43.     </div>
  44. </div>
  45.     $(function(){
  46.         var validation_el = $('<div>')
  47.             validation_el.addClass('validation-err alert alert-danger my-2')
  48.             validation_el.hide()
  49.         $('input[name="code"]').on('input',function(){
  50.             var code = $(this).val()
  51.                 $(this).removeClass("border-danger border-success")
  52.                 $(this).siblings(".validation-err").remove();
  53.             var err_el = validation_el.clone()
  54.  
  55.                 if(code == '')
  56.                 return false;
  57.  
  58.                 $.ajax({
  59.                     url:"validate.php",
  60.                     method:'POST',
  61.                     data:{code:code},
  62.                     dataType:'json',
  63.                     error:err=>{
  64.                         console.error(err)
  65.                         alert("An error occured while validating the data")
  66.                     },
  67.                     success:function(resp){
  68.                         if(Object.keys(resp).length > 0 && resp.field_name == 'code'){
  69.                            err_el.text(resp.msg)
  70.                            $('input[name="code"]').addClass('border-danger')
  71.                            $('input[name="code"]').after(err_el)
  72.                            err_el.show('slideDown')
  73.                            $('#submit').attr('disabled',true)
  74.                        }else{
  75.                            $('input[name="code"]').addClass('border-success')
  76.                            $('#submit').attr('disabled',false)
  77.                        }
  78.                    }
  79.                })
  80.        })
  81.  
  82.    })
  83. </script>

product_list.php

This file contains the product list interface. This includes the query that fetches the product data from the database.

  1. <div class="content py-3">
  2.     <h3 class="text-center fw-bolder">List of Products</h3>
  3.     <center><hr class="bg-primary mx-1 opacity-100" style="width:5em"></center>
  4.     <div class="card card-primary bg-light border-top-1 border-primary shadow rounded-0">
  5.         <div class="card-body rounded-0">
  6.             <table class="table table-bordered table-striped">
  7.                 <thead>
  8.                     <tr>
  9.                         <th class="py-1 px-2">#</th>
  10.                         <th class="py-1 px-2">Code</th>
  11.                         <th class="py-1 px-2">Name</th>
  12.                         <th class="py-1 px-2">Description</th>
  13.                         <th class="py-1 px-2">Price</th>
  14.                         <th class="py-1 px-2">Action</th>
  15.                     </tr>
  16.                 </thead>
  17.                 <tbody>
  18.                     <?php
  19.                    $i=1;
  20.                        $products = $conn->query("SELECT * FROM `product_list` order by `product_name` asc ");
  21.                         while($row = $products->fetch_assoc()):
  22.                     ?>
  23.                     <tr>
  24.                         <td class="py-1 px-2 text-center"><?= $i++; ?></td>
  25.                         <td class="py-1 px-2"><?= $row['code'] ?></td>
  26.                         <td class="py-1 px-2"><?= $row['product_name'] ?></td>
  27.                         <td class="py-1 px-2"><?= $row['description'] ?></td>
  28.                         <td class="py-1 px-2"><?= number_format($row['price'],2) ?></td>
  29.                         <td class="text-center py-1 px-2">
  30.                             <a href="./?page=edit_product&id=<?= $row['id'] ?>" class="btn btn-sm btn-primary rounded-0">Edit</a>
  31.                             <a href="./?page=delete_product&id=<?= $row['id'] ?>" class="btn btn-sm btn-danger rounded-0" onclick="return confirm('Are you sure to delete this product?')">Delete</a>
  32.                         </td>
  33.                     </tr>
  34.                     <?php endwhile; ?>
  35.                 </tbody>
  36.             </table>
  37.         </div>
  38.     </div>
  39. </div>

edit_product.php

This file contains the PHP and HTML scripts for editing the product details.

  1. <?php
  2. if(isset($_GET['id'])){
  3.    $qry = $conn->query("SELECT * FROM `product_list` where id = '{$_GET['id']}'");
  4.     if($qry->num_rows > 0){
  5.         $result = $qry->fetch_array();
  6.         foreach($result as $k => $v){
  7.             if(!is_numeric($k)){
  8.                 $$k = $v;
  9.             }
  10.         }
  11.     }else{
  12.         $_SESSION['flashdata']['type']='danger';
  13.         $_SESSION['flashdata']['msg']='Unable to load Update Product due to unknown ID.';
  14.         echo "<script>location.href='./?page=product_list';</script>";
  15.     }
  16. }else{
  17.     $_SESSION['flashdata']['type']='danger';
  18.     $_SESSION['flashdata']['msg']='Unable to load Update Product because ID # is required.';
  19.     echo "<script>location.href='./?page=product_list';</script>";
  20. }
  21. ?>
  22. <div class="content py-3">
  23.     <h3 class="text-center fw-bolder">Update Product</h3>
  24.     <center><hr class="bg-primary mx-1 opacity-100" style="width:5em"></center>
  25.     <div class="row justify-content-center">
  26.         <div class="card shadow col-md-8">
  27.             <div class="card-body">
  28.                 <div class="container-fluid py3">
  29.                     <form action="update_product.php" method="POST">
  30.                         <input type="hidden" name="id" value="<?= $_GET['id'] ?>">
  31.                         <div class="row">
  32.                             <div class="col-md-12 form-group">
  33.                                 <label for="code" class="control-label text-primary">Code</label>
  34.                                 <input type="text" max="50" name="code" id="code" autofocus class="form-control form-control-sm" value="<?= isset($code) ? $code : "" ?>" required>
  35.                             </div>
  36.                         </div>
  37.                         <div class="row">
  38.                             <div class="col-md-12 form-group">
  39.                                 <label for="product_name" class="control-label text-primary">Product Name</label>
  40.                                 <input type="text" name="product_name" id="product_name" class="form-control form-control-sm" value="<?= isset($product_name) ? $product_name : "" ?>" required>
  41.                             </div>
  42.                         </div>
  43.                         <div class="row">
  44.                             <div class="col-md-12 form-group">
  45.                                 <label for="description" class="control-label text-primary">Description</label>
  46.                                 <textarea rows="3" name="description" id="description" class="form-control form-control-sm" required><?= isset($description) ? $description : "" ?></textarea>
  47.                             </div>
  48.                         </div>
  49.                         <div class="row">
  50.                             <div class="col-md-12 form-group">
  51.                                 <label for="price" class="control-label text-primary">Price</label>
  52.                                 <input type="number" step="any" name="price" id="price" class="form-control form-control-sm text-end" value="<?= isset($price) ? $price : "" ?>" required>
  53.                             </div>
  54.                         </div>
  55.                         <div class="row">
  56.                             <div class="form-group col-md-12 text-center mt-4">
  57.                                 <button class="btn btn-primary rounded-0 col-3">Save</button>
  58.                                 <a class="btn btn-secondary rounded-0 col-3" href="./?page=product_list">Cancel</a>
  59.                             </div>
  60.                         </div>
  61.                     </form>
  62.                 </div>
  63.             </div>
  64.         </div>
  65.     </div>
  66. </div>
  67.     $(function(){
  68.         var validation_el = $('<div>')
  69.             validation_el.addClass('validation-err alert alert-danger my-2')
  70.             validation_el.hide()
  71.         $('input[name="code"]').on('input',function(){
  72.             var code = $(this).val()
  73.                 $(this).removeClass("border-danger border-success")
  74.                 $(this).siblings(".validation-err").remove();
  75.             var err_el = validation_el.clone()
  76.  
  77.                 if(code == '')
  78.                 return false;
  79.  
  80.                 $.ajax({
  81.                     url:"validate.php",
  82.                     method:'POST',
  83.                     data:{code:code,id : '<?= $_GET['id'] ?>'},
  84.                     dataType:'json',
  85.                     error:err=>{
  86.                         console.error(err)
  87.                         alert("An error occured while validating the data")
  88.                     },
  89.                     success:function(resp){
  90.                         if(Object.keys(resp).length > 0 && resp.field_name == 'code'){
  91.                            err_el.text(resp.msg)
  92.                            $('input[name="code"]').addClass('border-danger')
  93.                            $('input[name="code"]').after(err_el)
  94.                            err_el.show('slideDown')
  95.                        }else{
  96.                            $('input[name="code"]').addClass('border-success')
  97.                        }
  98.                    }
  99.                })
  100.        })
  101.  
  102.    })
  103. </script>

Creating PHP Queries

The following files our the script for saving, updating, and deleting products on the database. Save the following files using the filename provided before each scripts.

validate.php

This PHP Script contains the codes that validates the product code if theres a product with given product code has already exists.

  1. <?php
  2. require_once('db_connect.php');
  3. // extracting POST Variables
  4. extract($_POST);
  5.     $error = [];
  6.     $check = $conn->query("SELECT * FROM `product_list` where code = '{$code}'". (isset($id) && $id > 0 ? " and id != '{$id}' " : "" ));
  7.     if($check->num_rows > 0){
  8.         $error['field_name'] = 'code';
  9.         $error['msg']=" Code already exists on the product list";
  10.     }
  11.     echo json_encode($error);
  12. ?>

save_product.php

This PHP Script contains the codes that saves the new product created from the Add New Product Form to the database.

  1. <?php
  2. require_once('db_connect.php');
  3. // Escaping post string values
  4. foreach($_POST as $k => $v){
  5.     if(!is_numeric($v)){
  6.         $_POST[$k] = $conn->real_escape_string($v);
  7.     }
  8. }
  9. // extracing POST Variables
  10. extract($_POST);
  11. // Preparing Insert Query
  12. $stmt = $conn->prepare("INSERT INTO `product_list` (`code`,`product_name`,`description`,`price`) VALUES (?, ?, ?, ?)");
  13. if($stmt){
  14.     // Binding Insertion Parameters
  15.     $stmt->bind_param("sssd", $code, $product_name, $description, $price);
  16.  
  17.     // Executing the query
  18.     $save = $stmt->execute();
  19.     $_SESSION['flashdata']['type'] = 'success';
  20.     $_SESSION['flashdata']['msg'] = 'New Product was successfully added.';
  21.  
  22.     // Closing Query
  23.     $stmt->close();
  24.     header("location:./?page=product_list");
  25. }else{
  26.     $_SESSION['flashdata']['type'] = 'danger';
  27.     $_SESSION['flashdata']['msg'] = 'An error occurred while saving the data. Error: '.$conn->error;
  28.     header("location:".$_SERVER['HTTP_REFERER']);
  29. }
  30. // Closing the database Connection
  31. $conn->close();
  32. ?>

update_product.php

This PHP Script contains the code that updates the product details form the Edit Product Form to the Database.

  1. <?php
  2. require_once('db_connect.php');
  3. // Escaping post string values
  4. foreach($_POST as $k => $v){
  5.     if(!is_numeric($v)){
  6.         $_POST[$k] = $conn->real_escape_string($v);
  7.     }
  8. }
  9. // extracing POST Variables
  10. extract($_POST);
  11. // Preparing Insert Query
  12. $stmt = $conn->prepare("UPDATE `product_list` set `code` = ?, `product_name` = ?, `description` = ?, `price` = ? where id = ?");
  13. if($stmt){
  14.     // Binding Insertion Parameters
  15.     $stmt->bind_param("sssdi", $code, $product_name, $description, $price, $id);
  16.  
  17.     // Executing the query
  18.     $save = $stmt->execute();
  19.     $_SESSION['flashdata']['type'] = 'success';
  20.     $_SESSION['flashdata']['msg'] = 'Product was successfully updated.';
  21.  
  22.     // Closing Query
  23.     $stmt->close();
  24.     header("location:./?page=product_list");
  25. }else{
  26.     $_SESSION['flashdata']['type'] = 'danger';
  27.     $_SESSION['flashdata']['msg'] = 'An error occurred while saving the data. Error: '.$conn->error;
  28.     header("location:".$_SERVER['HTTP_REFERER']);
  29. }
  30. // Closing the database Connection
  31. $conn->close();
  32. ?>

delete_product.php

This PHP Script contains the code that removes/deletes the selected product from the database.

  1. <?php
  2. require_once('db_connect.php');
  3. if(isset($_GET['id'])){
  4.     $qry = $conn->query("SELECT * FROM `product_list` where id = '{$_GET['id']}'");
  5.     if($qry->num_rows <= 0){
  6.         $_SESSION['flashdata']['type']='danger';
  7.         $_SESSION['flashdata']['msg']='Unable to DELETE Product due to unknown ID.';
  8.         echo "<script>location.href='./?page=product_list';</script>";
  9.     }
  10. }else{
  11.     $_SESSION['flashdata']['type']='danger';
  12.     $_SESSION['flashdata']['msg']='Unable to DELETE Product because ID # is required.';
  13.     echo "<script>location.href='./?page=product_list';</script>";
  14. }
  15. // Preparing Insert Query
  16. $stmt = $conn->prepare("DELETE FROM `product_list` where id = ?");
  17. if($stmt){
  18.     // Binding Insertion Parameters
  19.     $stmt->bind_param("i", $_GET['id']);
  20.  
  21.     // Executing the query
  22.     $save = $stmt->execute();
  23.     $_SESSION['flashdata']['type'] = 'success';
  24.     $_SESSION['flashdata']['msg'] = 'Product was successfully deleted.';
  25.  
  26.     // Closing Query
  27.     $stmt->close();
  28.     header("location:./?page=product_list");
  29. }else{
  30.     $_SESSION['flashdata']['type'] = 'danger';
  31.     $_SESSION['flashdata']['msg'] = 'An error occurred while deleting the data. Error: '.$conn->error;
  32.     header("location:".$_SERVER['HTTP_REFERER']);
  33. }
  34. // Closing the database Connection
  35. $conn->close();
  36. ?>

Sample Snapshots

Product Form with Validation Error

Sample Snapshot

Product List

Sample Snapshot

That's it! You can now test the application that we created on your end and see if it is working meets our goal for this tutorial. If ever you have encountered any errors on your end, please review your codes and compare them to the codes that I provided above. I have also provided the working source code for this tutorial. You can download it by clicking the Download Button below this article.

DEMO VIDEO

That's the end of this tutorial. For any questions or queries, you can leave a comment below.

Explore more on this website for more Tutorials and Free Source Codes.

Happy Coding :)

Comments

Works like a dream except for the delete row. Notice: A session had already been started - ignoring session_start() in Z:\delete_product.php on line 2 Warning: Cannot modify header information - headers already sent by (output started at Z:\index.php:12) in Z:\web\delete_product.php on line 29 any ideas, have checked whitespace etc

Add new comment