How to Build a CRUD Application with React and PHP

Featured on Hashnode

In this blog post, we will create a CRUD (Create, Read, Update, Delete) application using React for the frontend and PHP for the backend. We will store our data in a MySQL database, communicate between the frontend and backend using Axios for HTTP requests, and manage our form submissions and record fetching.

Table of Contents

  1. Project Setup

  2. Frontend (React)

    • Creating the Insert, Update, Delete Form

    • Displaying Records

  3. Backend (PHP & MySQL)

    • Creating a Database Table

    • Writing the API for CRUD Operations

    • Fetching Records from the Database

  4. Final Thoughts


1. Project Setup

To start, you will need the following installed:

  • Node.js (for React)

  • PHP (for backend)

  • MySQL database

Create the React project using the following command:

npx create-react-app react-crud
cd react-crud
npm install axios react-router-dom

This will set up the frontend React application.

Next, on your server, set up the PHP backend with MySQL support.

2. Frontend (React)

Creating the Insert, Update, Delete Form

We will create a simple form that will allow users to insert, update, and delete records in the database. The form will collect user data (full name and email) and send it to the backend via Axios for handling.

Below is the code for handling the form:

import React, { useState } from 'react';
import axios from 'axios';
import '../css/style.css';
import ikoyi from '../images/ikoyi.jpeg';
import { NavLink } from 'react-router-dom';
import { BsPersonBadge, BsEnvelopeAtFill } from "react-icons/bs";

export default function Insert() {
  const [fullname, setFullname] = useState('');
  const [email, setEmail] = useState('');
  const [formid, setFormid] = useState('');

  const handleFormidSubmit = async (formType) => {
    setFormid(formType);

    const data = {
      fullname,
      email,
      formid: formType,
    };

    try {
      const response = await axios.post('https://your_url.com/crud', data, {
        headers: {
          'Content-Type': 'application/json',
        },
      });

      alert(response.data.message);
    } catch (error) {
      console.error("Error during form submission:", error);
      alert("Error processing the request.");
    }
  };

  return (
    <div className="myGrid">
      <div className="column1">
        <img src={ikoyi} alt="Description of the image" />
        <h1 className="centeredText">Crud Tutorial</h1>
      </div>
      <div className="column2">
        <div className="centeredDiv">
          <form>
            <div className="input-container">
              <input
                type="text"
                placeholder="Fullname"
                value={fullname}
                onChange={(e) => setFullname(e.target.value)}
                required
              />
              <span className='icon1'><BsPersonBadge /></span>
            </div>

            <div className="input-container">
              <input
                type="email"
                placeholder="Your Email"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                required
              />
              <span className='icon1'><BsEnvelopeAtFill /></span>
            </div>

            <div className="button-group">
              <button 
                type="button" 
                onClick={() => handleFormidSubmit('insert-form')}
              >
                Insert Record
              </button>
              <button 
                type="button" 
                onClick={() => handleFormidSubmit('update-form')}
              >
                Update Record
              </button>
              <button 
                type="button" 
                onClick={() => handleFormidSubmit('delete-form')}
              >
                Delete Record
              </button>
            </div>
          </form>
          <p>Back to Crud Menu <NavLink to='/'>Go to Menu</NavLink></p>
        </div>
      </div>
    </div>
  );
}

This component renders a form where the user can submit full name and email for three different actions: inserting, updating, or deleting a record.

Displaying Records

In this section, we'll display the records fetched from the database in a table:

import React, { useState, useEffect } from 'react';
import axios from 'axios';
import '../css/style.css';
import ikoyi from '../images/ikoyi.jpeg';
import { NavLink } from 'react-router-dom';

export default function Select() {
  const [records, setRecords] = useState([]);
  const [error, setError] = useState('');

  useEffect(() => {
    const fetchRecords = async () => {
      try {
        const response = await axios.get('https://your_url.com/get-records');
        if (response.data.status === 'success') {
          setRecords(response.data.data);
        } else {
          setError(response.data.message);
        }
      } catch (error) {
        console.error("Error fetching records:", error);
        setError("Error fetching records");
      }
    };

    fetchRecords();
  }, []);

  return (
    <div className="myGrid">
      <div className="column1">
        <img src={ikoyi} alt="Description of the image" />
        <h1 className="centeredText">Crud Tutorial</h1>
      </div>
      <div className="column2">
        <div className="centeredDiv">
          <h2>Select Record from Database</h2>
          {error && <p className="error-message">{error}</p>}
          {records.length > 0 ? (
            <table className="styled-table">
              <thead>
                <tr>
                  <th>Fullname</th>
                  <th>Email</th>
                </tr>
              </thead>
              <tbody>
                {records.map((record, index) => (
                  <tr key={index}>
                    <td>{record.fullname}</td>
                    <td>{record.email}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          ) : (
            <p>No records found</p>
          )}
          <p>Back to Crud Menu <NavLink to='/'>Go to Menu</NavLink></p>
        </div>
      </div>
    </div>
  );
}

3. Backend (PHP & MySQL)

Creating a Database Table

In MySQL, we will create a table named crud to store user data:

CREATE TABLE crud (
  id INT AUTO_INCREMENT PRIMARY KEY,
  fullname VARCHAR(255) NOT NULL,
  email VARCHAR(255) NOT NULL UNIQUE
);

This table contains two fields, fullname and email, with a unique constraint on the email.

Writing the API for CRUD Operations

Now let's write the PHP code to handle inserting, updating, deleting, and fetching records.

  1. Insert, Update, Delete Operations:
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization");

// Database connection details
$servername = "localhost";
$username = "your_db_username";
 $password = "your_db_password";
$dbname = "your_db_name";

// Function to sanitize input
function sanitize_input($data) {
    return htmlspecialchars(stripslashes(trim($data)));
}

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);

// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

// Read raw input data
$inputData = json_decode(file_get_contents("php://input"), true);

// Get POST data and sanitize inputs
$fullname = isset($inputData["fullname"]) ? sanitize_input($inputData["fullname"]) : '';
$email = isset($inputData["email"]) ? sanitize_input($inputData["email"]) : '';
$formid = isset($inputData["formid"]) ? sanitize_input($inputData["formid"]) : '';

// Perform the action based on formid
if ($formid === 'insert-form') {
    // INSERT operation
    $sql = "INSERT INTO crud (fullname, email) VALUES (?, ?)";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param("ss", $fullname, $email);

    if ($stmt->execute()) {
        echo json_encode(array('status' => 'success', 'message' => 'Record inserted successfully'));
    } else {
        echo json_encode(array('status' => 'error', 'message' => 'Error inserting record'));
    }

    $stmt->close();
} elseif ($formid === 'update-form') {
    // UPDATE operation (assuming update by email for simplicity)
    $sql = "UPDATE crud SET fullname=? WHERE email=?";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param("ss", $fullname, $email);

    if ($stmt->execute()) {
        echo json_encode(array('status' => 'success', 'message' => 'Record updated successfully'));
    } else {
        echo json_encode(array('status' => 'error', 'message' => 'Error updating record'));
    }

    $stmt->close();
} elseif ($formid === 'delete-form') {
    // DELETE operation (assuming delete by email for simplicity)
    $sql = "DELETE FROM crud WHERE email=?";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param("s", $email);

    if ($stmt->execute()) {
        echo json_encode(array('status' => 'success', 'message' => 'Record deleted successfully'));
    } else {
        echo json_encode(array('status' => 'error', 'message' => 'Error deleting record'));
    }

    $stmt->close();
} else {
    echo json_encode(array('status' => 'error', 'message' => 'Invalid form submission'));
}

// Close the connection
$conn->close();
  1. Selecting Record on the backend
<?php
// Add CORS headers to allow requests from different origins
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization");

// Database connection details
$servername = "localhost";
$username = "your_db_username";
 $password = "your_db_password";
$dbname = "your_db_name";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);

// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

// Fetch records from the database
$sql = "SELECT fullname, email FROM crud";
$result = $conn->query($sql);

if ($result->num_rows > 0) {
    $records = array();
    while ($row = $result->fetch_assoc()) {
        $records[] = $row;
    }
    echo json_encode(array('status' => 'success', 'data' => $records));
} else {
    echo json_encode(array('status' => 'error', 'message' => 'No records found'));
}

// Close the connection
$conn->close();
?>

Conclusion

In this post, we've covered the process of building a simple CRUD application using React and PHP. We set up a MySQL database to store our records and created a PHP backend to handle the necessary CRUD operations. Our React frontend allows users to interact with this backend seamlessly. You can now expand this application further by adding more features or integrating user authentication.