Showing posts with label application. Show all posts
Showing posts with label application. Show all posts

Saturday, 2 December 2023

Building a React.js CRUD Application with Vite, PHP API and MySQL

Building a React.js CRUD Application with Vite, PHP API, and MySQL


In this tutorial, we'll walk through the process of creating a full-stack CRUD (Create, Read, Update, Delete) application using React.js, Vite for the frontend, PHP for the backend, and MySQL as the database. This project will help you understand how to set up a modern development environment and integrate the different components seamlessly.

Prerequisites


Before getting started, make sure you have the following tools installed:

  • Node.js
  • npm (Node Package Manager)
  • PHP
  • Composer
  • MySQL

Steps for Create PHP React CRUD Application


  1. Installation
  2. Set Router for Fetch Data
  3. Create Fetch Data API
  4. Make Insert Data Component & Set Route
  5. Submit Form Data
  6. Set Router for Edit Data Component
  7. Make Update Data API
  8. Create Delete Data API




Step 1 - Installation


Here we have make CRUD Application by using React.js with PHP API. So first we want to download and install React.js on our local computer. So here we have use Vite tool and it is a front end tool which is used for building fast and optimized web application.

Now we want to download React Framework by using Vite. So first we have goes to command prompt and And here we have goes into directory from which we can run PHP application and for download and install React.js we have to run following command in terminal.


npm create vite@latest phpreactcrud


When you have run this command then it will create phpreactcrud directory and then after it will display JavaScript framework and from this list of framework we have to select React framework by pressing down key. And after selecting React and press enter then it has again ask for selecting JavaScript variant. So by pressing down key we have to select JavaScript and press enter.

After this, we have goes into phpreactcrud directory by run following command.


cd phpreactcrud


Inside your project directory, you'll need to install the project's dependencies using npm:


npm install


So after run this command it will start download React framework in phpreactcrud directory. Once download is complete, so we need to check React is properly install or not. So we have need to run following command.


npm run dev


When we have run this command then it will start React development server and provide us base url of our React Application. So from this url we can open React Application in the browser.

If React web page open in browser that means React is properly installed in our computer.

Directory Structure of React

Below you can find directory structure of React.js framework.


Directory Structure of React.js CRUD Application


Step 2 - Set Router for Fetch Data


This is second step for create PHP React.js CRUD application and under this step we have to set Router for Fetch Data. But before set Router for fetch data, first we have to install Bootstrap 5 library under this React CRUD Application.

So To use Bootstrap 5 in your React application, you need to install the Bootstrap package from npm. Bootstrap 5 comes with Sass, so you can take advantage of its customization features. Run the following command to install Bootstrap:


npm install bootstrap


So this command will download and install Bootstrap 5 library under this our React.js Application. Next we have to use Bootstrap library under this React CRUD Application.

So we have to open src/App.jsx file and for import the Bootstrap CSS at the top of the file:


import 'bootstrap/dist/css/bootstrap.min.css';


Next for display user data, we have to create Component/Userlist.jsx file and under this file, we want to import React, so we have to write following statement under this file.


import React from 'react';


So it will import React dependencies under this file. After this we have create React component for this Userlist by writing following code.

Component/Userlist.jsx

function Userlist(){
	return (
		<div className="card">
			<div className="card-header">
				<div className="row">
					<div className="col-md-6"><b>User Data</b></div>
					<div className="col-md-6">

					</div>
				</div>
			</div>
			<div className="card-body">
				<table className="table table-bordered">
					<thead>
						<tr>
							<th>First Name</th>
							<th>Last Name</th>
							<th>Email</th>
							<th>Action</th>
						</tr>
					</thead>
					<tbody>
					
					</tbody>
				</table>
			</div>
		</div>
	);
}


And for export this component, we have to write following code at the end of this file. So after write this code we can import this component in other file also.


export default Userlist;


Next we have open App.jsx file and under this file we have to first import React router dom library. So we have goes to command prompt and run following command. This command will download and install React router dom library under this App.jsx file.


npm install react-router-dom


After installing this library we can able to import React router dom library component like BrowserRouter, Routes, Route, Link by writing following statement under App.jsx file.


import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';


BrowserRouter - Here BrowserRouter component is represents the router for your application, And it is the key component from react router dom, which provided routing functionality to react application.

Routes - Routes component is typically used to define collection of routes.

Route - Route component is used to define, individual route in your application.

Link - Link component is used for creating hyperlink, that navigate to different parts of your application.

Next we want to import Component/Userlist.jsx file under this App.jsx file. So we have to add following statement under App.jsx file.


import Userlist from './Component/Userlist';


After import React router dom library and Userlist component, in below code you can find how to define route for fetch data.

src/App.jsx

import { useState } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
import Userlist from './Component/Userlist';

function App() {
    return(
        <div className="container">
            <h1 className="mt-5 mb-5 text-center"><b>PHP React.js CRUD Application - <span className="text-primary">Create Delete Data API - 8</span></b></h1>
            <BrowserRouter>
                <Routes>
                    <Route path="/" element={<Userlist />} />
                </Routes>
            </BrowserRouter>
        </div>
    )
}

export default App



src/Component/Userlist.jsx

import React from 'react';

function Userlist(){

	return (
		<div className="card">
			<div className="card-header">
				<div className="row">
					<div className="col-md-6"><b>User Data</b></div>
					<div className="col-md-6">
						
					</div>
				</div>
			</div>
			<div className="card-body">
				<table className="table table-bordered">
					<thead>
						<tr>
							<th>First Name</th>
							<th>Last Name</th>
							<th>Email</th>
							<th>Action</th>
						</tr>
					</thead>
					<tbody>
					
					</tbody>
				</table>
			</div>
		</div>
	);
}

export default Userlist;




Step 3 - Create Fetch Data API


After set Router for Fetch Data, now we want to make PHP API for fetch data from MySQL table. But before this we have to write JavaScript under Component/Userlist.jsx file for send fetch data request to PHP API.

Source Code of Create Fetch Data API

src/Component/Userlist.jsx

import React, { useEffect, useState } from 'react';

function Userlist(){
	const [users, setUsers] = useState([]);

	useEffect(() => {
		const apiUrl = 'http://localhost/tutorial/phpreactcrud/api/action.php'; //This URL change according to path of your PHP Script

		fetch(apiUrl)
		.then((response) => response.json())
		.then((data) => {
			setUsers(data);
		});

	}, []);

	return (
		<div className="card">
			<div className="card-header">
				<div className="row">
					<div className="col-md-6"><b>User Data</b></div>
					<div className="col-md-6">
						
					</div>
				</div>
			</div>
			<div className="card-body">
				<table className="table table-bordered">
					<thead>
						<tr>
							<th>First Name</th>
							<th>Last Name</th>
							<th>Email</th>
							<th>Action</th>
						</tr>
					</thead>
					<tbody>
					{users.map((user, index) => (
						<tr key={index}>
							<td>{user.first_name}</td>
							<td>{user.last_name}</td>
							<td>{user.email}</td>
							<td>
								
							</td>
						</tr>
					))}
					</tbody>
				</table>
			</div>
		</div>
	);
}

export default Userlist;


1 - Import Statements:


import React, { useEffect, useState } from 'react';


  • The code imports the necessary functionalities from the react library.
  • useEffect is a hook used for side effects in functional components, and useState is a hook for managing state.

2 - Component Definition:


function Userlist(){


  • The functional component named Userlist is defined.

3 - State Initialization:


const [users, setUsers] = useState([]);


  • This line initializes a state variable users using the useState hook. The setUsers function is used to update the state.

4 - Data Fetching using useEffect:


useEffect(() => {
    const apiUrl = 'http://localhost/tutorial/phpreactcrud/api/action.php';

    fetch(apiUrl)
    .then((response) => response.json())
    .then((data) => {
        setUsers(data);
    });

}, []);


  • The useEffect hook is used to perform side effects in functional components. In this case, it fetches data from a specified API endpoint when the component mounts ([] as the dependency array means it runs once when the component mounts).
  • The data fetched is expected to be in JSON format, and it updates the users state with the received data.

5 - Rendering JSX:


return (
    <div className="card">
        {/* ... */}
    </div>
);


  • The return statement contains JSX code that represents the structure of the component.

6 - JSX Structure:

  • The component renders a Bootstrap-styled card with a header and body.
  • The body contains a table displaying user data with columns for "First Name," "Last Name," "Email," and an "Action" column.

7 - Mapping Through User Data:


{users.map((user, index) => (
    <tr key={index}>
        <td>{user.first_name}</td>
        <td>{user.last_name}</td>
        <td>{user.email}</td>
        <td>
            {/* Action content */}
        </td>
    </tr>
))}


  • The component maps through the users array and renders a table row (</tr>) for each user.
  • User details such as first name, last name, and email are displayed in the corresponding columns.

8 - Export Statement:


export default Userlist;


  • The Userlist component is exported as the default export of this module, making it available for use in other parts of the application.
api/action.php

<?php

header("Access-Control-Allow-Origin:* ");

header("Access-Control-Allow-Headers:* ");

header("Access-Control-Allow-Methods:* ");

$connect = new PDO("mysql:host=127.0.0.1;dbname=testing", "root", "password");

$method = $_SERVER['REQUEST_METHOD']; //return GET, POST, PUT, DELETE

if($method === 'GET')
{
	//fetch all user

		$query = "SELECT * FROM sample_users ORDER BY id DESC";

		$result = $connect->query($query, PDO::FETCH_ASSOC);

		$data = array();

		foreach($result as $row)
		{
			$data[] = $row;
		}

		echo json_encode($data);
	
}


?>


This PHP code is designed to handle HTTP requests, specifically for the GET method, and it interacts with a MySQL database to retrieve data. Let's break down the code:

1 - Cross-Origin Resource Sharing (CORS) Headers:


header("Access-Control-Allow-Origin:* ");
header("Access-Control-Allow-Headers:* ");
header("Access-Control-Allow-Methods:* ");


  • These lines set up CORS headers, allowing cross-origin requests from any origin (*). CORS headers are necessary for web applications hosted on one domain to make requests to a different domain.

2 - Database Connection:


$connect = new PDO("mysql:host=127.0.0.1;dbname=testing", "root", "password");


  • It establishes a connection to a MySQL database named "testing" on the local server (127.0.0.1). The username is "root," and the password is "password." This connection is created using the PDO (PHP Data Objects) extension.

3 - Request Method Check:


$method = $_SERVER['REQUEST_METHOD'];


  • It retrieves the HTTP request method (GET, POST, PUT, DELETE) from the $_SERVER superglobal.

4 - Handling GET Requests:


if ($method === 'GET') {
    //fetch all user
    $query = "SELECT * FROM sample_users ORDER BY id DESC";
    $result = $connect->query($query, PDO::FETCH_ASSOC);
    
    $data = array();
    foreach ($result as $row) {
        $data[] = $row;
    }
    echo json_encode($data);
}


  • If the request method is GET, the code executes a SELECT query to retrieve all records from the "sample_users" table, ordering them by the "id" column in descending order.
  • The result of the query is fetched using the query method, and the data is extracted using a foreach loop.
  • The retrieved data is then encoded as JSON using json_encode and echoed back to the client.

This PHP code handles GET requests, connects to a MySQL database, retrieves all records from a specific table, and returns the data in JSON format with appropriate CORS headers to allow cross-origin requests.




Step 4 - Make Insert Data Component & Set Route


Once we have fetch data from MySQL database and display on web page under this React.js CRUD Application. Next We will create insert data component in which we will create Add user data form, and then after we will set router of that insert data component under this React.js PHP CRUD Application.

src/Component/Add.jsx

import React, { useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';

function Add(){

	let navigate = useNavigate();

	const [user, setUser] = useState({
		first_name : '',
		last_name : '',
		email : ''
	});

	const handleChange = (event) => {
		const { name, value } = event.target;

		setUser({
			...user,
			[name] : value
		});
	};

	return (
		<div className="card">
			<div className="card-header">
				<div className="row">
					<div className="col-md-6">Add User</div>
					<div className="col-md-6">
						<Link to="/" className="btn btn-success btn-sm float-end">View All</Link>
					</div>
				</div>
			</div>
			<div className="card-body">
				<div className="row">
					<div className="col-md-4">&nbsp;</div>
					<div className="col-md-4">
						<form method="POST">
							<div className="mb-3">
								<label>First Name</label>
								<input type="text" name="first_name" className="form-control" onChange={handleChange} />
							</div>
							<div className="mb-3">
								<label>Last Name</label>
								<input type="text" name="last_name" className="form-control" onChange={handleChange} />
							</div>
							<div className="mb-3">
								<label>Email</label>
								<input type="email" name="email" className="form-control" onChange={handleChange} />
							</div>
							<div className="mb-3">
								<input type="submit" className="btn btn-primary" value="Add" />
							</div>
						</form>
					</div>
				</div>
			</div>
		</div>
	);
}

export default Add;


This React.js code defines a functional component called Add that represents a form for adding a new user. It uses the useNavigate hook from react-router-dom to programmatically navigate between different views. Let's break down the code:

1 - Import Statements:


import React, { useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';


  • The code imports the necessary functionalities from the react library, including the useState hook.
  • It also imports Link and useNavigate from react-router-dom. Link is used to create navigation links, and useNavigate is a hook used for programmatic navigation.

2 - Component Definition:


function Add(){


  • The functional component named Add is defined.

3 - Navigation Setup:


let navigate = useNavigate();


  • The useNavigate hook is used to get the navigate function, which can be used to navigate between different views in a React application.

4 - State Initialization:


const [user, setUser] = useState({
    first_name : '',
    last_name : '',
    email : ''
});


  • This line initializes a state variable user using the useState hook. The state represents the user data with properties first_name, last_name, and email.

5 - Event Handler Function:


const handleChange = (event) => {
    const { name, value } = event.target;

    setUser({
        ...user,
        [name] : value
    });
};


  • The handleChange function is an event handler for input changes. It uses object destructuring to extract the name and value from the changed input element.
  • The setUser function is then used to update the user state by spreading the existing state and updating the property corresponding to the changed input.

6 - Rendering JSX:


return (
    <div className="card">
        {/* ... */}
    </div>
);


  • The return statement contains JSX code that represents the structure of the component.

7 - JSX Structure:

  • The component renders a Bootstrap-styled card with a header and body.
  • The body contains a form with input fields for "First Name," "Last Name," and "Email," along with a submit button labeled "Add."

8 - Navigation Link:


<Link to="/" className="btn btn-success btn-sm float-end">View All</Link>


  • This is a Link component that creates a link to the root path ("/"). It's styled as a Bootstrap button and is labeled "View All."
  • Clicking on this link will navigate the user to the specified path.

9 - Form Input Fields:


<input type="text" name="first_name" className="form-control" onChange={handleChange} />
<input type="text" name="last_name" className="form-control" onChange={handleChange} />
<input type="email" name="email" className="form-control" onChange={handleChange} />


  • These input fields are controlled components, meaning their values are controlled by the state (user).
  • The onChange event is set to the handleChange function, ensuring that any changes to the input fields update the state.

10 - Submit Button:


<input type="submit" className="btn btn-primary" value="Add" />


  • This is a submit button for the form. It triggers the submission of the form data.

11 - Export Statement:


export default Add;


  • The Add component is exported as the default export of this module, making it available for use in other parts of the application.

This component provides a form for adding a new user. It captures input changes, updates the component state accordingly, and allows for the submission of the form data.

After creating this src/Component/Add.jsx file, now we want to import in src/App.jsx file.

src/App.jsx

import { useState } from 'react'
import 'bootstrap/dist/css/bootstrap.min.css';
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
import Userlist from './Component/Userlist';
import Add from './Component/Add';

function App() {
    return(
        <div className="container">
            <h1 className="mt-5 mb-5 text-center"><b>PHP React.js CRUD Application - <span className="text-primary">Create Delete Data API - 8</span></b></h1>
            <BrowserRouter>
                <Routes>
                    <Route path="/" element={<Userlist />} />
                    <Route path="/add" element={<Add />} />
                </Routes>
            </BrowserRouter>
        </div>
    )
}

export default App



1 - Import Statements:


import Add from './Component/Add';


  • Component Add are imported from separate files.

2 - React Router Setup:


<BrowserRouter>
    <Routes>
        /* ... */
        <Route path="/add" element={<Add />} />
    </Routes>
</BrowserRouter>


  • The BrowserRouter component from react-router-dom is used to set up routing for the application.
  • Inside it, the Routes component defines different routes using the Route component. Two routes are defined:
    • The path /add renders the Add component.

So this way we can create Add user form component and import into App.jsx file.




Step 5 - Submit Form Data


Now you can move to How to submit form data by using React handle submit function and then after you will learn how to make PHP API for Insert Form data under this React CRUD Application.

src/Component/Add.jsx

import React, { useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';

function Add(){

	let navigate = useNavigate();

	const [user, setUser] = useState({
		first_name : '',
		last_name : '',
		email : ''
	});

	const handleChange = (event) => {
		const { name, value } = event.target;

		setUser({
			...user,
			[name] : value
		});
	};

	const handleSubmit = (event) => {

		event.preventDefault();

		fetch('http://localhost/tutorial/phpreactcrud/api/action.php', {
			method : 'POST',
			headers : {
				'Content-Type' : 'application/json'
			},
			body : JSON.stringify(user)
		})
		.then((response) => response.json())
		.then((data) => {
			navigate("/");
		})

	};

	return (
		<div className="card">
			<div className="card-header">
				<div className="row">
					<div className="col-md-6">Add User</div>
					<div className="col-md-6">
						<Link to="/" className="btn btn-success btn-sm float-end">View All</Link>
					</div>
				</div>
			</div>
			<div className="card-body">
				<div className="row">
					<div className="col-md-4">&nbsp;</div>
					<div className="col-md-4">
						<form method="POST" onSubmit={handleSubmit}>
							<div className="mb-3">
								<label>First Name</label>
								<input type="text" name="first_name" className="form-control" onChange={handleChange} />
							</div>
							<div className="mb-3">
								<label>Last Name</label>
								<input type="text" name="last_name" className="form-control" onChange={handleChange} />
							</div>
							<div className="mb-3">
								<label>Email</label>
								<input type="email" name="email" className="form-control" onChange={handleChange} />
							</div>
							<div className="mb-3">
								<input type="submit" className="btn btn-primary" value="Add" />
							</div>
						</form>
					</div>
				</div>
			</div>
		</div>
	);
}

export default Add;


1 - Event Handler Function (handleSubmit):


const handleSubmit = (event) => {
    event.preventDefault();

    fetch('http://localhost/tutorial/phpreactcrud/api/action.php', {
        method : 'POST',
        headers : {
            'Content-Type' : 'application/json'
        },
        body : JSON.stringify(user)
    })
    .then((response) => response.json())
    .then((data) => {
        navigate("/");
    });
};


  • The handleSubmit function is an event handler for form submission. It prevents the default form submission behavior using event.preventDefault().
  • It then makes a POST request to the specified API endpoint ('http://localhost/tutorial/phpreactcrud/api/action.php') with the user data in JSON format.
  • Upon successful submission, it navigates the user back to the root path ("/") using the navigate function.

2 - Form onSubmit Event Handler:


<form method="POST" onSubmit={handleSubmit}>


  • The onSubmit attribute is set to the handleSubmit function.
  • This means that when the form is submitted (either by clicking a submit button or pressing Enter within a form field), the handleSubmit function will be called.
api/action.php

<?php

header("Access-Control-Allow-Origin:* ");

header("Access-Control-Allow-Headers:* ");

header("Access-Control-Allow-Methods:* ");

$connect = new PDO("mysql:host=127.0.0.1;dbname=testing", "root", "password");

$method = $_SERVER['REQUEST_METHOD']; //return GET, POST, PUT, DELETE

if($method === 'GET')
{	
	//fetch all user

	$query = "SELECT * FROM sample_users ORDER BY id DESC";

	$result = $connect->query($query, PDO::FETCH_ASSOC);

	$data = array();

	foreach($result as $row)
	{
		$data[] = $row;
	}

	echo json_encode($data);
}

if($method === 'POST')
{
	$form_data = json_decode(file_get_contents('php://input'));

	$data = array(
		':first_name'		=>	$form_data->first_name,
		':last_name'		=>	$form_data->last_name,
		':email'			=>	$form_data->email
	);

	$query = "
	INSERT INTO sample_users (first_name, last_name, email) VALUES (:first_name, :last_name, :email);
	";

	$statement = $connect->prepare($query);

	$statement->execute($data);

	echo json_encode(["success" => "done"]);
}

?>


This PHP code is a simple server-side script that handles HTTP requests, specifically for the POST method. It interacts with a MySQL database to insert data submitted through a JSON-encoded payload.


if($method === 'POST') {
    // Process POST data

    $form_data = json_decode(file_get_contents('php://input'));

    $data = array(
        ':first_name'		=>	$form_data->first_name,
        ':last_name'		=>	$form_data->last_name,
        ':email'			=>	$form_data->email
    );

    $query = "
    INSERT INTO sample_users (first_name, last_name, email) VALUES (:first_name, :last_name, :email);
    ";

    $statement = $connect->prepare($query);

    $statement->execute($data);

    echo json_encode(["success" => "done"]);
}


  • If the request method is POST, the code proceeds to handle the incoming data.
  • It uses json_decode to parse the JSON data received from the client via the php://input stream.
  • The parsed data is then used to construct an associative array $data with keys corresponding to database columns.
  • A SQL query is prepared to insert the data into the "sample_users" table.
  • The query is executed using the prepared statement, and a success message is echoed back as a JSON response.

In summary, this PHP script checks for incoming POST requests, parses the JSON data, inserts it into a MySQL database, and responds with a JSON success message.




Step 6 - Set Router for Edit Data Component


Under this step, you can find how to create Edit component under this React Crud application and then after, we will set route for that edit component, under this React Application.

src/Component/Userlist.jsx

import React, { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';

function Userlist(){
	const [users, setUsers] = useState([]);

	useEffect(() => {
		const apiUrl = 'http://localhost/tutorial/phpreactcrud/api/action.php';

		fetch(apiUrl)
		.then((response) => response.json())
		.then((data) => {
			setUsers(data);
		});

	}, []);

	return (
		<div className="card">
			<div className="card-header">
				<div className="row">
					<div className="col-md-6"><b>User Data</b></div>
					<div className="col-md-6">
						<Link to="/add" className="btn btn-success btn-sm float-end">Add</Link>
					</div>
				</div>
			</div>
			<div className="card-body">
				<table className="table table-bordered">
					<thead>
						<tr>
							<th>First Name</th>
							<th>Last Name</th>
							<th>Email</th>
							<th>Action</th>
						</tr>
					</thead>
					<tbody>
					{users.map((user, index) => (
						<tr key={index}>
							<td>{user.first_name}</td>
							<td>{user.last_name}</td>
							<td>{user.email}</td>
							<td>
								<Link to={`/edit/${user.id}`} className="btn btn-warning btn-sm">Edit</Link>
							</td>
						</tr>
					))}
					</tbody>
				</table>
			</div>
		</div>
	);
}

export default Userlist;


Here We have uses the Link component from react-router-dom to create a navigation link styled as a Bootstrap button. Clicking the link navigates the user to an "edit" route with a dynamic parameter, specifically the id property of a user object. This pattern is often used to implement edit functionality in React applications.

src/Component/Edit.jsx

import React, {useState, useEffect} from 'react';

import { Link, useNavigate, useParams } from 'react-router-dom';

function Edit(){

	let navigate = useNavigate();
	
	const {user_id} = useParams();

	const [user, setUser] = useState({
		first_name : '',
		last_name : '',
		email : ''
	});

	const handleChange = (event) => {
		const {name, value} = event.target;

		setUser({
			...user,
			[name] : value
		});
	};

	const fetchUserData = () => {
		fetch(`http://localhost/tutorial/phpreactcrud/api/action.php?id=${user_id}`)
		.then((response) => response.json())
		.then((data) => {
			setUser(data);
		});
	};

	useEffect(() => {
		fetchUserData();
	}, []);

	return (
		<div className="card">
			<div className="card-header">
				<div className="row">
					<div className="col-md-6">Edit User</div>
					<div className="col-md-6">
						<Link to="/" className="btn btn-success btn-sm float-end">View All</Link>
					</div>
				</div>
			</div>
			<div className="card-body">
				<div className="row">
					<div className="col-md-4">&nbsp;</div>
					<div className="col-md-4">
						<form method="POST">
							<div className="mb-3">
								<label>First Name</label>
								<input type="text" name="first_name" className="form-control" value={user.first_name} onChange={handleChange} />
							</div>
							<div className="mb-3">
								<label>Last Name</label>
								<input type="text" name="last_name" className="form-control" value={user.last_name} onChange={handleChange} />
							</div>
							<div className="mb-3">
								<label>Email</label>
								<input type="email" name="email" className="form-control" value={user.email} onChange={handleChange} />
							</div>
							<div className="mb-3">
								<input type="submit" className="btn btn-primary" value="Edit" />
							</div>
						</form>
					</div>
				</div>
			</div>
		</div>
	)
}

export default Edit;


1 - Import Statements:


import React, {useState, useEffect} from 'react';
import { Link, useNavigate, useParams } from 'react-router-dom';


  • The code imports the necessary functionalities from the react and react-router-dom libraries.
  • useParams is used to extract parameters from the URL.

2 - Component Definition:


function Edit() {


  • The functional component named Edit is defined.

3 - Hooks and State Initialization:


let navigate = useNavigate();

const [user, setUser] = useState({
    first_name: '',
    last_name: '',
    email: ''
});


  • The useNavigate hook is used to get the navigate function for programmatic navigation.
  • The useState hook initializes the user state, representing user information with properties first_name, last_name, and email.

4 - Event Handler Function (handleChange):


const handleChange = (event) => {
    const { name, value } = event.target;

    setUser({
        ...user,
        [name]: value
    });
};

  • The handleChange function is an event handler for input changes. It updates the user state based on the changed input field.

5 - Fetch User Data Function (fetchUserData):


const fetchUserData = () => {
    fetch(`http://localhost/tutorial/phpreactcrud/api/action.php?id=${user_id}`)
        .then((response) => response.json())
        .then((data) => {
            setUser(data);
        });
};


  • The fetchUserData function uses the fetch API to retrieve user data based on the id parameter from the URL.
  • The fetched data is then used to update the user state.

6 - UseEffect Hook for Fetching Data:


useEffect(() => {
    fetchUserData();
}, []);


  • The useEffect hook is used to execute the fetchUserData function when the component mounts (empty dependency array []).
  • This ensures that user data is fetched once when the component is rendered.

Rendering JSX:


return (
    <div className="card">
        {/* ... */}
    </div>
);


  • The return statement contains JSX code that represents the structure of the component.

7 - JSX Structure:

  • The component renders a Bootstrap-styled card with a header and body.
  • The body contains a form with input fields for "First Name," "Last Name," and "Email," along with a submit button labeled "Edit."
  • The input values are controlled by the user state, ensuring that the form fields display the current user data.

9 - Navigation Link:


<Link to="/" className="btn btn-success btn-sm float-end">View All</Link>


  • This is a Link component that creates a link to the root path ("/"). It's styled as a Bootstrap button and is labeled "View All."
  • Clicking on this link will navigate the user back to the root path.

10 - Form Input Fields:


<input type="text" name="first_name" className="form-control" value={user.first_name} onChange={handleChange} />
<input type="text" name="last_name" className="form-control" value={user.last_name} onChange={handleChange} />
<input type="email" name="email" className="form-control" value={user.email} onChange={handleChange} />


  • These input fields are controlled components, meaning their values are controlled by the user state.
  • The value attribute is set to the corresponding property of the user state.
  • The onChange event is set to the handleChange function, ensuring that any changes to the input fields update the state.

11 - Submit Button:


<input type="submit" className="btn btn-primary" value="Edit" />


  • This is a submit button for the form. It triggers the submission of the form data.

12 - Export Statement:


export default Edit;


  • The Edit component is exported as the default export of this module, making it available for use in other parts of the application.

In summary, this Edit component is a form for editing user data. It uses the useEffect hook to fetch user data when the component mounts, and it provides a form with controlled input fields. The user can edit the information, and clicking the "Edit" button triggers an update operation, which is typically handled on the server side.

src/App.jsx

import { useState } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
import Userlist from './Component/Userlist';
import Add from './Component/Add';
import Edit from './Component/Edit';

function App() {
    return(
        <div className="container">
            <h1 className="mt-5 mb-5 text-center"><b>PHP React.js CRUD Application - <span className="text-primary">Create Delete Data API - 8</span></b></h1>
            <BrowserRouter>
                <Routes>
                    <Route path="/" element={<Userlist />} />
                    <Route path="/add" element={<Add />} />
                    <Route path="/edit/:user_id" element={<Edit />} />
                </Routes>
            </BrowserRouter>
        </div>
    )
}

export default App



  • Component Edit is imported from it's respective file.

<Route path="/edit/:user_id" element={<Edit />} />


  • The third one maps the "/edit/:user_id" path to the Edit component. The :user_id is a dynamic parameter that can be accessed in the Edit component.
api/action.php

<?php

header("Access-Control-Allow-Origin:* ");

header("Access-Control-Allow-Headers:* ");

header("Access-Control-Allow-Methods:* ");

$connect = new PDO("mysql:host=127.0.0.1;dbname=testing", "root", "password");

$method = $_SERVER['REQUEST_METHOD']; //return GET, POST, PUT, DELETE

if($method === 'GET')
{
	if(isset($_GET['id']))
	{
		//fetch single user
		$query = "SELECT * FROM sample_users WHERE id = '".$_GET["id"]."'";

		$result = $connect->query($query, PDO::FETCH_ASSOC);

		$data = array();

		foreach($result as $row)
		{
			$data['first_name'] = $row['first_name'];

			$data['last_name'] = $row['last_name'];

			$data['email'] = $row['email'];

			$data['id'] = $row['id'];
		}

		echo json_encode($data);
	}
	else 
	{
		//fetch all user

		$query = "SELECT * FROM sample_users ORDER BY id DESC";

		$result = $connect->query($query, PDO::FETCH_ASSOC);

		$data = array();

		foreach($result as $row)
		{
			$data[] = $row;
		}

		echo json_encode($data);
	}	
}

if($method === 'POST')
{
	$form_data = json_decode(file_get_contents('php://input'));

	$data = array(
		':first_name'		=>	$form_data->first_name,
		':last_name'		=>	$form_data->last_name,
		':email'			=>	$form_data->email
	);

	$query = "
	INSERT INTO sample_users (first_name, last_name, email) VALUES (:first_name, :last_name, :email);
	";

	$statement = $connect->prepare($query);

	$statement->execute($data);

	echo json_encode(["success" => "done"]);
}

?>


1 - Check for id Parameter:


if(isset($_GET['id']))


  • Checks if the id parameter is set in the query string of the URL. If id parameter value is set then single user data will be fetch otherwise all user data will be fetch.

2 - Fetch Single User Data


//fetch single user
		$query = "SELECT * FROM sample_users WHERE id = '".$_GET["id"]."'";

		$result = $connect->query($query, PDO::FETCH_ASSOC);

		$data = array();

		foreach($result as $row)
		{
			$data['first_name'] = $row['first_name'];

			$data['last_name'] = $row['last_name'];

			$data['email'] = $row['email'];

			$data['id'] = $row['id'];
		}

		echo json_encode($data);


  • If the id parameter is set, it constructs a SQL query to fetch a single user with the specified ID.
  • Executes the SQL query using PDO (PHP Data Objects) to fetch the data associated with the specified user ID.
  • Iterates over the result set and prepares the data for the single user. It assigns the user's first name, last name, email, and ID to the $data array.
  • Encodes the prepared data as JSON and echoes it back as the response.

In summary, this PHP script handles GET requests to fetch user data. If the request includes an id parameter, it fetches a single user; otherwise, it fetches all users. The script uses PDO for database interaction and outputs the result as JSON.




Step 7 - Make Update Data API


After creating Edit Component under this React CRUD Application and fetch single user data. Now you have to learn, how to submit edit user form data under this React application. And then after, We will make API for update user data under this React CRUD application.

src/Component/Edit.jsx

import React, {useState, useEffect} from 'react';

import { Link, useNavigate, useParams } from 'react-router-dom';

function Edit(){

	let navigate = useNavigate();

	const {user_id} = useParams();

	const [user, setUser] = useState({
		first_name : '',
		last_name : '',
		email : ''
	});

	const handleChange = (event) => {
		const {name, value} = event.target;

		setUser({
			...user,
			[name] : value
		});
	};

	const fetchUserData = () => {
		fetch(`http://localhost/tutorial/phpreactcrud/api/action.php?id=${user_id}`)
		.then((response) => response.json())
		.then((data) => {
			setUser(data);
		});
	};

	useEffect(() => {
		fetchUserData();
	}, []);

	const handleSubmit = (event) => {

		event.preventDefault();

		fetch(`http://localhost/tutorial/phpreactcrud/api/action.php?id=${user_id}`, {
			method : 'PUT',
			headers : {
				'Content-Type': 'application/json'
			},
			body : JSON.stringify(user)
		})
		.then((response) => response.json())
		.then((data) => {
			navigate("/");
		});

	};

	return (
		<div className="card">
			<div className="card-header">
				<div className="row">
					<div className="col-md-6">Edit User</div>
					<div className="col-md-6">
						<Link to="/" className="btn btn-success btn-sm float-end">View All</Link>
					</div>
				</div>
			</div>
			<div className="card-body">
				<div className="row">
					<div className="col-md-4">&nbsp;</div>
					<div className="col-md-4">
						<form method="POST" onSubmit={handleSubmit}>
							<div className="mb-3">
								<label>First Name</label>
								<input type="text" name="first_name" className="form-control" value={user.first_name} onChange={handleChange} />
							</div>
							<div className="mb-3">
								<label>Last Name</label>
								<input type="text" name="last_name" className="form-control" value={user.last_name} onChange={handleChange} />
							</div>
							<div className="mb-3">
								<label>Email</label>
								<input type="email" name="email" className="form-control" value={user.email} onChange={handleChange} />
							</div>
							<div className="mb-3">
								<input type="submit" className="btn btn-primary" value="Edit" />
							</div>
						</form>
					</div>
				</div>
			</div>
		</div>
	)
}

export default Edit;


1 - Form Submission Function (handleSubmit):


const handleSubmit = (event) => {
    event.preventDefault();

    fetch(`http://localhost/tutorial/phpreactcrud/api/action.php?id=${user_id}`, {
        method: 'PUT',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(user)
    })
    .then((response) => response.json())
    .then((data) => {
        navigate("/");
    });
};


  • The handleSubmit function is called when the form is submitted.
  • It prevents the default form submission, sends a PUT request to update the user data, and then navigates to the root path (/) using the navigate function.

2 - Call JavaScript handleSubmit function


<form method="POST" onSubmit={handleSubmit}>
  {/* Form contents go here */}
</form>


  • The onSubmit attribute is set to a JavaScript function handleSubmit. This function will be called when the form is submitted.
  • The handleSubmit function is expected to handle the form submission logic. It usually includes tasks such as preventing the default form submission behavior, gathering form data, and sending it to the server.
api/action.php

<?php

header("Access-Control-Allow-Origin:* ");

header("Access-Control-Allow-Headers:* ");

header("Access-Control-Allow-Methods:* ");

$connect = new PDO("mysql:host=127.0.0.1;dbname=testing", "root", "password");

$method = $_SERVER['REQUEST_METHOD']; //return GET, POST, PUT, DELETE

if($method === 'GET')
{
	if(isset($_GET['id']))
	{
		//fetch single user
		$query = "SELECT * FROM sample_users WHERE id = '".$_GET["id"]."'";

		$result = $connect->query($query, PDO::FETCH_ASSOC);

		$data = array();

		foreach($result as $row)
		{
			$data['first_name'] = $row['first_name'];

			$data['last_name'] = $row['last_name'];

			$data['email'] = $row['email'];

			$data['id'] = $row['id'];
		}

		echo json_encode($data);
	}
	else 
	{
		//fetch all user

		$query = "SELECT * FROM sample_users ORDER BY id DESC";

		$result = $connect->query($query, PDO::FETCH_ASSOC);

		$data = array();

		foreach($result as $row)
		{
			$data[] = $row;
		}

		echo json_encode($data);
	}

	
}

if($method === 'POST')
{
	//Insert User Data

	$form_data = json_decode(file_get_contents('php://input'));

	$data = array(
		':first_name'		=>	$form_data->first_name,
		':last_name'		=>	$form_data->last_name,
		':email'			=>	$form_data->email
	);

	$query = "
	INSERT INTO sample_users (first_name, last_name, email) VALUES (:first_name, :last_name, :email);
	";

	$statement = $connect->prepare($query);

	$statement->execute($data);

	echo json_encode(["success" => "done"]);
}

if($method === 'PUT')
{
	//Update User Data

	$form_data = json_decode(file_get_contents('php://input'));

	$data = array(
		':first_name'		=>	$form_data->first_name,
		':last_name'		=>	$form_data->last_name,
		':email'			=>	$form_data->email,
		':id'				=>	$form_data->id
	);

	$query = "
	UPDATE sample_users 
	SET first_name = :first_name, 
	last_name = :last_name, 
	email = :email 
	WHERE id = :id
	";

	$statement = $connect->prepare($query);

	$statement->execute($data);

	echo json_encode(["success" => "done"]);
}
?>


This PHP code handles the logic for updating user data when the HTTP request method is PUT.

1 - Check Request Method:


if ($method === 'PUT') {
    // Update User Data
    // ...
}


  • This block checks if the HTTP request method is PUT. If true, it proceeds to handle the update operation.

2 - Decode JSON Data:


$form_data = json_decode(file_get_contents('php://input'));


  • Reads and decodes JSON data from the request body sent by the client. This data likely contains information about the user to be updated, including the new values for first_name, last_name, email, and id.

3 - Prepare Data for Update:


$data = array(
    ':first_name' => $form_data->first_name,
    ':last_name'  => $form_data->last_name,
    ':email'      => $form_data->email,
    ':id'         => $form_data->id
);


  • Creates an associative array ($data) with placeholders for the values to be updated in the SQL query.

4 - SQL Update Query:


$query = "
UPDATE sample_users 
SET first_name = :first_name, 
last_name = :last_name, 
email = :email 
WHERE id = :id
";


  • Defines an SQL query to update the user data in the sample_users table. The placeholders :first_name, :last_name, :email, and :id will be replaced with the corresponding values from the $data array.

5 - Prepare and Execute SQL Statement:


$statement = $connect->prepare($query);
$statement->execute($data);


  • Prepares the SQL statement using the PDO extension.
  • Executes the prepared statement with the data provided. This updates the user data in the database.

6 - JSON Response:


echo json_encode(["success" => "done"]);


  • Outputs a JSON response indicating the success of the update operation. This response is sent back to the client.

In summary, when a PUT request is received, this PHP code decodes the JSON data sent by the client, prepares the data for the update, executes an SQL query to update the user data in the database, and sends a JSON response indicating the success of the operation.




Step 8 - Create Delete Data API


Now we have come to last step of this React.js PHP CRUD Application and under this step you can find how to delete data from MySQL table by using PHP API and React.js function.

src/Component/Userlist.jsx

import React, { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';

function Userlist(){
	const [users, setUsers] = useState([]);

	useEffect(() => {
		const apiUrl = 'http://localhost/tutorial/phpreactcrud/api/action.php';

		fetch(apiUrl)
		.then((response) => response.json())
		.then((data) => {
			setUsers(data);
		});

	}, []);

	const handleDelete = (user_id) => {
		if(confirm("Are your sure you want to remove it?"))
		{
			fetch(`http://localhost/tutorial/phpreactcrud/api/action.php?id=${user_id}`, {
				method : 'DELETE'
			})
			.then((response) => response.json())
			.then((data) => {
				setUsers((prevUser) => prevUser.filter((user) => user.id !== user_id));
			});
		}
	};

	return (
		<div className="card">
			<div className="card-header">
				<div className="row">
					<div className="col-md-6"><b>User Data</b></div>
					<div className="col-md-6">
						<Link to="/add" className="btn btn-success btn-sm float-end">Add</Link>
					</div>
				</div>
			</div>
			<div className="card-body">
				<table className="table table-bordered">
					<thead>
						<tr>
							<th>First Name</th>
							<th>Last Name</th>
							<th>Email</th>
							<th>Action</th>
						</tr>
					</thead>
					<tbody>
					{users.map((user, index) => (
						<tr key={index}>
							<td>{user.first_name}</td>
							<td>{user.last_name}</td>
							<td>{user.email}</td>
							<td>
								<Link to={`/edit/${user.id}`} className="btn btn-warning btn-sm">Edit</Link>&nbsp;
								<button type="button" onClick={() => handleDelete(user.id)} className="btn btn-danger btn-sm">Delete</button>
							</td>
						</tr>
					))}
					</tbody>
				</table>
			</div>
		</div>
	);
}

export default Userlist;


1 - Delete User Handler:


const handleDelete = (user_id) => {
		if(confirm("Are your sure you want to remove it?"))
		{
			fetch(`http://localhost/tutorial/phpreactcrud/api/action.php?id=${user_id}`, {
				method : 'DELETE'
			})
			.then((response) => response.json())
			.then((data) => {
				setUsers((prevUser) => prevUser.filter((user) => user.id !== user_id));
			});
		}
	};


  • Defines a function handleDelete to handle the deletion of a user.
  • Prompts the user with a confirmation dialog before proceeding with the deletion.
  • Sends a DELETE request to the server API with the user ID to be deleted.
  • Updates the users state by removing the deleted user from the array.

2 - Create Delete Button


<button type="button" onClick={() => handleDelete(user.id)} className="btn btn-danger btn-sm">Delete</button>


  • "Delete" button triggers the handleDelete function when clicked.
api/action.php

if($method === 'DELETE')
{
	//Delete User Data
	
	$data = array(
		':id' => $_GET['id']
	);

	$query = "DELETE FROM sample_users WHERE id = :id";

	$statement = $connect->prepare($query);

	$statement->execute($data);

	echo json_encode(["success" => "done"]);
}


This PHP code handles the logic for deleting a user when the HTTP request method is DELETE.

1 - Check Request Method:


if ($method === 'DELETE') {
    // Delete User Data
    // ...
}


  • This block checks if the HTTP request method is DELETE. If true, it proceeds to handle the delete operation.

2 - Prepare Data for Deletion:


$data = array(
    ':id' => $_GET['id']
);


  • Creates an associative array ($data) with a placeholder (:id) for the user ID to be deleted. The user ID is obtained from the query parameters ($_GET['id']).

3 - SQL Delete Query:


$query = "DELETE FROM sample_users WHERE id = :id";


  • Defines an SQL query to delete a user from the sample_users table based on the provided user ID.

4 - Prepare and Execute SQL Statement:


$statement = $connect->prepare($query);
$statement->execute($data);


  • Prepares the SQL statement using the PDO extension.
  • Executes the prepared statement with the data provided. This deletes the user from the database.

5 - JSON Response:


echo json_encode(["success" => "done"]);


  • Outputs a JSON response indicating the success of the delete operation. This response is sent back to the client.

In summary, when a DELETE request is received, this PHP code prepares the user ID for deletion, executes an SQL query to delete the user data from the database, and sends a JSON response indicating the success of the delete operation.




Conclusion


Congratulations! You've successfully built a full-stack CRUD application using React.js, Vite, PHP, and MySQL. This project provides a solid foundation for more complex applications, and you can further enhance it by adding features like authentication, error handling, and improved user interfaces.

Remember to follow best practices for security, such as validating and sanitizing user input on the server side, securing your database connections, and implementing proper authentication mechanisms. Happy coding!





Friday, 1 September 2023

Efficient Node.js CRUD App with MySQL: Enhanced by Bootstrap Offcanvas for a Seamless User Experience

Efficient Node.js CRUD App with MySQL: Enhanced by Bootstrap Offcanvas for a Seamless User Experience


In today's fast-paced world of web development, creating applications that can seamlessly manage data is a must. That's where CRUD (Create, Read, Update, Delete) applications come into play, enabling users to interact with data stored in databases efficiently. In this article, we'll guide you through building an efficient Node.js CRUD application, supercharged by MySQL as the database, and enhanced with Bootstrap Offcanvas for an exceptional user experience.

Getting Started with Node.js and MySQL


Before diving into the Offcanvas enhancements, let's set the foundation by creating a basic Node.js CRUD application with MySQL. We'll go step by step:

Step 1: Setting Up Your Development Environment


Make sure you have Node.js and MySQL installed on your system. If not, you can download and install them from their respective websites.

Step 2: Project Initialization


Create a new directory for your project and navigate to it in your terminal. Run the following command to initialize a Node.js project:


npm init -y

Step 3: Installing Dependencies


Install the necessary dependencies: express, mysql2, and body-parser using the following command:


npm install express mysql2 body-parser


Step 4: Creating the Server


Now, create a server.js file and set up your Express server. Import the required modules and configure your server:


const express = require('express');

const bodyParser = require('body-parser');

const mysql = require('mysql2');

const app = express();

app.use(bodyParser.urlencoded({ extended : true }));

const connection = mysql.createConnection({
	host : 'localhost',
	user : 'root',
	password : '',
	database : 'testing'
});

connection.connect((error) => {
	if(error){
		console.log('Error connecting to MySQL:', err);
		return;
	}
	console.log('Connected to MySQL database');
});

app.listen(3000, () => {
	console.log('Server is listening on port 3000');
});


Step 5: Setting Up CRUD Routes


Implement your CRUD operations by defining routes for creating, reading, updating, and deleting data in your MySQL database. Here's a simplified example for the "read" operation:

Index Route

When someone navigates to the root URL of our server, we serve an HTML file named form.html. We're essentially setting up the initial interface for users to interact with.


app.get('/', (request, response) => {
	response.sendFile(__dirname + '/form.html');
});


Select or Fetch Data


This route will handle requests for fetching data from our MySQL database.


app.get('/fetchData', (request, response) => {
	const { draw, start, length, order, columns, search } = request.query;

	const column_index = order && order[0] && order[0].column;

	const column_sort_order = order === undefined ? 'desc' : request.query.order[0]['dir'];

	const column_name = column_index ? columns[column_index] : 'id';

	const search_value = search.value;

	const search_query = search_value ? ` WHERE name LIKE '%${search_value}%' OR email LIKE '%${search_value}%'` : '';

	const query1 = `SELECT id, name, email FROM user ${search_query} ORDER BY ${column_name} ${column_sort_order} LIMIT ${start}, ${length}`;

	const query2 = `SELECT COUNT(*) AS Total FROM user`;

	const query3 = `SELECT COUNT(*) AS Total FROM user ${search_query}`;

	connection.query(query1, (dataError, dataResult) => {

		connection.query(query2, (totalDataError, totalDataResult) => {

			connection.query(query3, (totalFilterDataError, totalFilterDataResult) => {

				response.json({
					draw : request.query.draw,
					recordsTotal : totalDataResult[0]['Total'],
					recordsFiltered : totalFilterDataResult[0]['Total'],
					data : dataResult
				});

			})

		})

	})
});


Insert Update Delete Data


This route will handle requests for Insert Update Delete data from our MySQL database.


app.post('/submitData', (request, response) => {
	const id = request.body.id;
	const name = request.body.name;
	const email = request.body.email;
	const action = request.body.action;
	let query;
	let data;
	let message;
	if(action === 'Insert'){
		query = `INSERT INTO user (name, email) VALUES (?, ?)`;
		data = [name, email];
		message = 'Data has been inserted';
	}

	if(action === 'Edit'){
		query = `UPDATE user SET name = ?, email = ? WHERE id = ?`;
		data = [name, email, id];
		message = 'Data has been updated';
	}

	if(action === 'Delete'){
		query = `DELETE FROM user WHERE id = ?`;
		data = [id];
		message = 'Data has been deleted';
	}

	connection.query(query, data, (error, result) => {
		response.json({'message' : message});
	});
});


Fetch Single Data


This route will be used for fetch single data from MySQL Database.


app.get('/fetchData/:id', (request, response) => {
	const query = `SELECT * FROM user WHERE id = ?`;

	connection.query(query, [request.params.id], (error, result) => {
		response.json(result[0]);
	});
});





Enhancing User Experience with Bootstrap Offcanvas


Now that we have our Node.js CRUD application up and running, it's time to enhance the user experience with Bootstrap Offcanvas. The Offcanvas component provides a sleek and non-intrusive way to interact with data.

Step 1: Adding Bootstrap to Your Project


Include Bootstrap CSS and JavaScript files in your HTML. You can either download them and host them locally or use a Content Delivery Network (CDN). Here's an example of using CDN links:


<!doctype html>
<html lang="en">
    <head>
        <!-- Required meta tags -->
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <!-- Bootstrap CSS -->
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
        <link href="https://cdn.datatables.net/1.13.6/css/dataTables.bootstrap5.min.css" rel="stylesheet">

        <title>Node.js CRUD with MySQL & Bootstrap Offcanvas</title>
    </head>
    <body>

        <script src="https://code.jquery.com/jquery-3.7.0.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
        <script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
        <script src="https://cdn.datatables.net/1.13.6/js/dataTables.bootstrap5.min.js"></script>

    </body>
</html>


Step 2: Creating an Offcanvas


Now, let's implement an Offcanvas for editing user data. Add a button to trigger the Offcanvas:


<button type="button" class="btn btn-primary btn-sm float-end" onclick="addData()">Add</button>


Create the Offcanvas element with a form for editing user data:


<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvas_component">
            <div class="offcanvas-header">
                <h5 class="offcanvas-title" id="offcanvasLabel">Add Data</h5>
                <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
            </div>
            <div class="offcanvas-body">

            </div>
        </div>


Step 3: Implementing the Edit Form


Inside the Offcanvas body, add a form for adding or editing user data. So for this, we have make form field by using javascript function which we can you for both Insert or updata of data also.


function makeForm(id = '', name = '', email = '', action = 'Insert')
    {
        const output = `
        <div class="mb-3">
            <label for="name">Name:</label>
            <input type="text" name="name" id="name" class="form-control" value="${name}" />
        </div>
        <div class="mb-3">
            <label for="email">Email:</label>
            <input type="email" name="email" id="email" class="form-control" value="${email}" />
        </div>
        <input type="hidden" name="action" id="action" value="${action}" />
        <input type="hidden" name="id" id="id" value="${id}" />
        <input type="submit" class="btn btn-primary" onclick="submitForm();" value="${action}" />
        `;
        return output;
    }


Step 4: JavaScript for Offcanvas Interaction


Finally, use JavaScript to handle the Offcanvas interactions. Add an event listener to open the Offcanvas when the "Edit User" button is clicked:


let offcanvas;

    let offcanvas_body = document.querySelector('.offcanvas-body');

    let offcanvas_component = document.querySelector('#offcanvas_component');

    let offcanvasLabel = document.querySelector('#offcanvasLabel');

    offcanvas = new bootstrap.Offcanvas(offcanvas_component);


You can further enhance this by pre-populating the form with user data for editing and implementing the update functionality.

Complete Source Code


server.js

const express = require('express');

const bodyParser = require('body-parser');

const mysql = require('mysql2');

const app = express();

app.use(bodyParser.urlencoded({ extended : true }));

const connection = mysql.createConnection({
	host : 'localhost',
	user : 'root',
	password : '',
	database : 'testing'
});

connection.connect((error) => {
	if(error){
		console.log('Error connecting to MySQL:', err);
		return;
	}
	console.log('Connected to MySQL database');
});

app.get('/', (request, response) => {
	response.sendFile(__dirname + '/form.html');
});

app.get('/fetchData', (request, response) => {
	const { draw, start, length, order, columns, search } = request.query;

	const column_index = order && order[0] && order[0].column;

	const column_sort_order = order === undefined ? 'desc' : request.query.order[0]['dir'];

	const column_name = column_index ? columns[column_index] : 'id';

	const search_value = search.value;

	const search_query = search_value ? ` WHERE name LIKE '%${search_value}%' OR email LIKE '%${search_value}%'` : '';

	const query1 = `SELECT id, name, email FROM user ${search_query} ORDER BY ${column_name} ${column_sort_order} LIMIT ${start}, ${length}`;

	const query2 = `SELECT COUNT(*) AS Total FROM user`;

	const query3 = `SELECT COUNT(*) AS Total FROM user ${search_query}`;

	connection.query(query1, (dataError, dataResult) => {

		connection.query(query2, (totalDataError, totalDataResult) => {

			connection.query(query3, (totalFilterDataError, totalFilterDataResult) => {

				response.json({
					draw : request.query.draw,
					recordsTotal : totalDataResult[0]['Total'],
					recordsFiltered : totalFilterDataResult[0]['Total'],
					data : dataResult
				});

			})

		})

	})
});

app.post('/submitData', (request, response) => {
	const id = request.body.id;
	const name = request.body.name;
	const email = request.body.email;
	const action = request.body.action;
	let query;
	let data;
	let message;
	if(action === 'Insert'){
		query = `INSERT INTO user (name, email) VALUES (?, ?)`;
		data = [name, email];
		message = 'Data has been inserted';
	}

	if(action === 'Edit'){
		query = `UPDATE user SET name = ?, email = ? WHERE id = ?`;
		data = [name, email, id];
		message = 'Data has been updated';
	}

	if(action === 'Delete'){
		query = `DELETE FROM user WHERE id = ?`;
		data = [id];
		message = 'Data has been deleted';
	}

	connection.query(query, data, (error, result) => {
		response.json({'message' : message});
	});
});

app.get('/fetchData/:id', (request, response) => {
	const query = `SELECT * FROM user WHERE id = ?`;

	connection.query(query, [request.params.id], (error, result) => {
		response.json(result[0]);
	});
});

app.listen(3000, () => {
	console.log('Server is listening on port 3000');
});




form.html

<!doctype html>
<html lang="en">
    <head>
        <!-- Required meta tags -->
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <!-- Bootstrap CSS -->
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
        <link href="https://cdn.datatables.net/1.13.6/css/dataTables.bootstrap5.min.css" rel="stylesheet">

        <title>Node.js CRUD with MySQL & Bootstrap Offcanvas</title>
    </head>
    <body>
        <div class="container">
            <h1 class="text-danger text-center mt-3"><b>Node.js CRUD with MySQL & Bootstrap Offcanvas - Delete Data</b></h1>
            <div class="card mt-5">
                <div class="card-header">
                    <div class="row">
                        <div class="col-md-11"><b>Node.js CRUD with MySQL & Bootstrap Offcanvas</b></div>
                        <div class="col-md-1">
                            <button type="button" class="btn btn-primary btn-sm float-end" onclick="addData()">Add</button>
                        </div>
                    </div>
                </div>
                <div class="card-body">
                    <div class="table-responsive">
                        <table class="table table-bordered" id="sample_data">
                            <thead>
                                <tr>
                                    <th>Name</th>
                                    <th>Email</th>
                                    <th>Action</th>
                                </tr>
                            </thead>
                            <tbody></tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>

        <div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvas_component">
            <div class="offcanvas-header">
                <h5 class="offcanvas-title" id="offcanvasLabel">Add Data</h5>
                <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
            </div>
            <div class="offcanvas-body">

            </div>
        </div>

        <!-- Optional JavaScript; choose one of the two! -->

        <!-- Option 1: Bootstrap Bundle with Popper -->
        


        <script src="https://code.jquery.com/jquery-3.7.0.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
        <script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
        <script src="https://cdn.datatables.net/1.13.6/js/dataTables.bootstrap5.min.js"></script>

    </body>
</html>

<script>

$(document).ready(function(){

    $('#sample_data').DataTable({
        ajax : '/fetchData',
        processing : true,
        serverSide : true,
        serverMethod : 'GET',
        order : [],
        columns : [
            { data : 'name' },
            { data : 'email' },
            {
                data : null,
                render : function (data, type, row){
                    return `<button class="btn btn-warning btn-sm" onclick="fetchData(${data.id})">Edit</button>&nbsp;<button class="btn btn-danger btn-sm" onclick="deleteData(${data.id})">Delete</button>`;
                }
            }
        ]
    });

});

    let offcanvas;

    let offcanvas_body = document.querySelector('.offcanvas-body');

    let offcanvas_component = document.querySelector('#offcanvas_component');

    let offcanvasLabel = document.querySelector('#offcanvasLabel');

    offcanvas = new bootstrap.Offcanvas(offcanvas_component);

    function addData()
    {
        offcanvas_body.innerHTML = makeForm();
        offcanvas.show();
    }

    function makeForm(id = '', name = '', email = '', action = 'Insert')
    {
        const output = `
        <div class="mb-3">
            <label for="name">Name:</label>
            <input type="text" name="name" id="name" class="form-control" value="${name}" />
        </div>
        <div class="mb-3">
            <label for="email">Email:</label>
            <input type="email" name="email" id="email" class="form-control" value="${email}" />
        </div>
        <input type="hidden" name="action" id="action" value="${action}" />
        <input type="hidden" name="id" id="id" value="${id}" />
        <input type="submit" class="btn btn-primary" onclick="submitForm();" value="${action}" />
        `;
        return output;
    }

    function submitForm()
    {
        const id = document.querySelector('#id').value;
        const name = document.querySelector('#name').value;
        const email = document.querySelector('#email').value;
        const action = document.querySelector('#action').value;

        $.ajax({
            url : '/submitData',
            method : 'POST',
            data : {id : id, name : name, email : email, action : action},
            dataType : 'JSON',
            success : function(data){
                $('#sample_data').DataTable().ajax.reload();
                offcanvas.hide();
                alert(data.message);
            }
        });
    }

    function fetchData(id)
    {
        $.ajax({
            url : '/fetchData/'+id,
            dataType : 'JSON',
            success : function(data){
                offcanvas_body.innerHTML = makeForm(data.id, data.name, data.email, 'Edit');
                offcanvasLabel.innerHTML = 'Edit Data';
                offcanvas.show();
            }
        });
    }

    function deleteData(id){
        let output = `
        <div class="text-center">
            <h3 class="text-danger mb-4">Are you sure you want to remove this data?</h3>
            <input type="hidden" id="id" value="${id}" />
            <input type="hidden" id="action" value="Delete" />
            <input type="hidden" id="name" value="" />
            <input type="hidden" id="email" value="" />
            <button type="button" class="btn btn-info" onclick="submitForm()">OK</button>
            <button type="button" class="btn btn-default" data-bs-dismiss="offcanvas">Cancel</button>
        </div>
        `;

        offcanvas_body.innerHTML = output;
        offcanvasLabel.innerHTML = 'Delete Data Confirmation';
        offcanvas.show();
    }

</script>


Run Node Application


For run Node.js Application, we have goes to terminal and goes into our working directory and run following command.


node server.js


This command will start our Node server and for check output in browser, we have to open this url in the browser window.


http://localhost:3000/


Conclusion


In this article, we've walked through the process of building an efficient Node.js CRUD application with MySQL. We've also explored how to enhance the user experience by integrating Bootstrap Offcanvas for a seamless and visually appealing interface. By combining the power of Node.js, MySQL, and Bootstrap Offcanvas, you can create dynamic and user-friendly applications that excel in data management.

Now, it's your turn to explore and expand upon these concepts to build feature-rich CRUD applications tailored to your specific requirements. Happy coding!

Monday, 7 January 2019

Twitter Like Follow Unfollow System in PHP using Ajax jQuery

From this post, you can learn how to make Follow and Unfollow system like Twitter which you can create in PHP using Ajax jQuery Mysql and Bootstrap. There are many viewers has requested to use PHP to build a Twitter like system. If you know on Twitter can post short News in Tweets format, and that tweets will be visible to those Twitter user who has follow this share user. When user share any news or tweets, that will be visible to his followers. So, this type of system we will make in PHP using Ajax jQuery and Mysql Database.

IF you are looking for any Social Networking Application for you colleage project, Then this post will help you to make small Follow Unfollow Application in PHP using Ajax step by step. On every publish of video tutorial of this post, you can find updated source code under this post. So, here we will show you How to develop twitter like follow and Unfollow system using Ajax in PHP script. Because most of this Social Networking sites are make in PHP Ajax. Here we have also use Bootstrap library for CSS purpose for make this system. So, here we will make dynamic follow unfollow application in PHP using Ajax.






Following are the main functionality of this follow unfollow system.

  • New User Registration
  • Login form for registered user
  • Authenticated User can edit his or here profile with upload profile image
  • User can share post, and list post
  • List User with follow unfollow button
  • Display number of followers of each user
  • Main functionality is to follow or unfollow other user post
  • Display dynamic results will be display if user click on follow unfollo button
  • All data will display using Ajax without refresh of web page
  • If you user follow any user, then he can also unfollow that user again
  • User can view follow user post on their timeline
  • User can comment on other user post
  • User can view comment on post
  • User can repost other user post on their timeline
  • User can see how many time particular post has been reposted
  • User can like other user post
  • User can like particular post only one time
  • User can view number of like on particular post
  • User can view username who has like post in Bootstrap tooltip
  • Share image or Video with Post
  • URL Content Extract with preview
  • Search User feature
  • View all post of single user on one page

So, Above are the main functionality of this follow unfollow system in PHP using Ajax jQuery Mysql and Bootstrap. Below you can find source code of Ajax based follow unfollow system.



Video Tutorial


Part 1




Part 2




Part 3




Part 4




Part 5




Part 6




Part 7




Part 8




Part 9




Part 10




Part 11




Part 12



Source Code


Database


Run follow SQL script, it will make three table like tbl_twitter_user, tbl_samples_post and tbl_follow in your PHPMysqmin. Follow Unfollow system has been use this three table for make application.


CREATE TABLE `tbl_follow` (
  `follow_id` int(11) NOT NULL AUTO_INCREMENT,
  `sender_id` int(11) NOT NULL,
  `receiver_id` int(11) NOT NULL,
  PRIMARY KEY (`follow_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

CREATE TABLE `tbl_samples_post` (
  `post_id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `post_content` text NOT NULL,
  `post_datetime` datetime NOT NULL,
  PRIMARY KEY (`post_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

CREATE TABLE `tbl_twitter_user` (
  `user_id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(150) NOT NULL,
  `password` varchar(150) NOT NULL,
  `name` varchar(150) NOT NULL,
  `profile_image` varchar(150) NOT NULL,
  `bio` text NOT NULL,
  `follower_number` int(11) NOT NULL,
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

CREATE TABLE `tbl_comment` (
  `comment_id` int(11) NOT NULL AUTO_INCREMENT,
  `post_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `comment` text NOT NULL,
  `timestamp` datetime NOT NULL,
  PRIMARY KEY (`comment_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;

CREATE TABLE `tbl_like` (
  `like_id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `post_id` int(11) NOT NULL,
  PRIMARY KEY (`like_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;



database_connection.php


This PHP file is used for make database connection. This is common file which we will used in all files for make Mysql Database connection.


<?php

//database_connection.php

$connect = new PDO("mysql:host=localhost;dbname=testing", "root", "");

function Count_notification($connect, $receiver_id)
{
 $query = "
 SELECT COUNT(notification_id) as total 
 FROM tbl_notification 
 WHERE notification_receiver_id = '".$receiver_id."' 
 AND read_notification = 'no'
 ";

 $statement = $connect->prepare($query);

 $statement->execute();

 $result = $statement->fetchAll();

 foreach($result as $row)
 {
  return $row["total"];
 }
}

function Load_notification($connect, $receiver_id)
{
 $query = "
 SELECT * FROM tbl_notification 
 WHERE notification_receiver_id = '".$receiver_id."' 
 ORDER BY notification_id DESC
 ";
 $statement = $connect->prepare($query);

 $statement->execute(); 

 $result = $statement->fetchAll();

 $total_row = $statement->rowCount();

 $output = '';

 if($total_row > 0)
 {
  foreach($result as $row)
  {
   $output .= '<li><a href="#">'.$row["notification_text"].'</a></li>';
  }
 }
 return $output;
}

function Get_user_name($connect, $user_id)
{
 $query = "
 SELECT username FROM tbl_twitter_user 
 WHERE user_id = '".$user_id."'
 ";

 $statement = $connect->prepare($query);

 $statement->execute();

 $result = $statement->fetchAll();

 foreach($result as $row)
 {
  return $row["username"];
 }
}

function count_retweet($connect, $post_id)
{
 $query = "
 SELECT * FROM tbl_repost 
 WHERE post_id = '".$post_id."'
 ";
 $statement = $connect->prepare($query);
 $statement->execute();
 return $statement->rowCount();
}

function count_comment($connect, $post_id)
{
 $query = "
 SELECT * FROM tbl_comment 
 WHERE post_id = '".$post_id."'
 ";
 $statement = $connect->prepare($query);
 $statement->execute();
 return $statement->rowCount();
}

function make_follow_button($connect, $sender_id, $receiver_id)
{
 $query = "
 SELECT * FROM tbl_follow 
 WHERE sender_id = '".$sender_id."' 
 AND receiver_id = '".$receiver_id."'
 ";
 $statement = $connect->prepare($query);
 $statement->execute();
 $total_row = $statement->rowCount();
 $output = '';
 if($total_row > 0)
 {
  $output = '<button type="button" name="follow_button" class="btn btn-warning action_button" data-action="unfollow" data-sender_id="'.$sender_id.'"> Following</button>';
 }
 else
 {
  $output = '<button type="button" name="follow_button" class="btn btn-info action_button" data-action="follow" data-sender_id="'.$sender_id.'"><i class="glyphicon glyphicon-plus"></i> Follow</button>';
 }
 return $output;
}

function count_total_post_like($connect, $post_id)
{
 $query = "
 SELECT * FROM tbl_like 
 WHERE post_id = '".$post_id."'
 ";

 $statement = $connect->prepare($query);

 $statement->execute();

 return $statement->rowCount();
}

function Get_user_id($connect, $username)
{
 $query = "
 SELECT user_id FROM tbl_twitter_user 
 WHERE username = '".$username."'
 "; 
 $statement = $connect->prepare($query);
 $statement->execute();
 $result = $statement->fetchAll();
 foreach($result as $row)
 {
  return $row["user_id"];
 }
}


?>




register.php


For any dynamic web application, we have to first make register form. So, here also first we want to make user registration system. So, new user can register into system. So, for make any dynamic system, here we have make this register form. In this system, here we have validate username already exists or not. If username already exists then user cannot register into system. In this registration system we have also validate user password by re-entering password. So, this is basic validation, which we have use here for make registration system for Follow Unfollow system using PHP with Ajax jQuery Mysql and Bootstrap.


<!--
//register.php
!-->

<?php

include('database_connection.php');

session_start();

$message = '';

if(isset($_SESSION['user_id']))
{
 header('location:index.php');
}

if(isset($_POST['register']))
{
 $username = trim($_POST["username"]);
 $password = trim($_POST["password"]);
 $check_query = "
 SELECT * FROM tbl_twitter_user 
 WHERE username = :username
 ";
 $statement = $connect->prepare($check_query);
 $check_data = array(
  ':username'  => $username
 );
 if($statement->execute($check_data))
 {
  if($statement->rowCount() > 0)
  {
   $message .= '<p><label>Username already taken</label></p>';
  }
  else
  {
   if(empty($username))
   {
    $message .= '<p><label>Username is required</label></p>';
   }
   if(empty($password))
   {
    $message .= '<p><label>Password is required</label></p>';
   }
   else
   {
    if($password != $_POST["confirm_password"])
    {
     $message .= '<p><label>Password not match</label></p>';
    }
   }
   if($message == '')
   {
    $data = array(
     ':username'  => $username,
     ':password'  => password_hash($password, PASSWORD_DEFAULT)
    );

    $query = "
    INSERT INTO tbl_twitter_user 
    (username, password) 
    VALUES (:username, :password)
    ";

    $statement = $connect->prepare($query);

    if($statement->execute($data))
    {
     $message = '<label>Registration Completed</label>';
    }
   }
  }
 }
}

?>

<html>  
    <head>  
        <title>Twitter Like Follow Unfollow System in PHP using Ajax jQuery</title>  
  <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    </head>  
    <body>  
        <div class="container">
   <br />
   
   <h3 align="center">Twitter Like Follow Unfollow System in PHP using Ajax jQuery</a></h3><br />
   <br />
   <div class="panel panel-default">
      <div class="panel-heading">Register</div>
    <div class="panel-body">
     <form method="post">
      <span class="text-danger"><?php echo $message; ?></span>
      <div class="form-group">
       <label>Enter Username</label>
       <input type="text" name="username" class="form-control" />
      </div>
      <div class="form-group">
       <label>Enter Password</label>
       <input type="password" name="password" id="password" class="form-control" />
      </div>
      <div class="form-group">
       <label>Re-enter Password</label>
       <input type="password" name="confirm_password" id="confirm_password" class="form-control" />
      </div>
      <div class="form-group">
       <input type="submit" name="register" class="btn btn-info" value="Register" />
      </div>
      <div align="center">
       <a href="login.php">Login</a>
      </div>
     </form>
    </div>
   </div>
  </div>
    </body>  
</html>


login.php


Once you have make registration system in Follow Unfollow application. After registration you have to make login page for authenticate user login details like username and password. Here password will be validate by using password_hash() method. Because at the time registration we have store password in hash format. If user has enter proper details, then his for validate user is login or not in whole system, we have store user details under $_SESSION variable.


<!--
//login.php
!-->

<?php

include('database_connection.php');

session_start();

$message = '';

if(isset($_SESSION['user_id']))
{
 header('location:index.php');
}

if(isset($_POST["login"]))
{
 $query = "
 SELECT * FROM tbl_twitter_user 
    WHERE username = :username
 ";
 $statement = $connect->prepare($query);
 $statement->execute(
  array(
      ':username' => $_POST["username"]
     )
 );
 $count = $statement->rowCount();
 if($count > 0)
 {
  $result = $statement->fetchAll();
  foreach($result as $row)
  {
   if(password_verify($_POST['password'], $row['password']))
   {
    $_SESSION['user_id'] = $row['user_id'];
    $_SESSION['username'] = $row['username'];
    header('location:index.php');
   }
   else
   {
    $message = '<label>Wrong Password</label>';
   }
  }
 }
 else
 {
  $message = '<label>Wrong Username</labe>';
 }
}


?>

<html>  
    <head>  
        <title>Twitter Like Follow Unfollow System in PHP using Ajax jQuery</title>  
  <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    </head>  
    <body>  
        <div class="container">
   <br />
   
   <h3 align="center">Twitter Like Follow Unfollow System in PHP using Ajax jQuery</a></h3><br />
   <br />
   <div class="panel panel-default">
      <div class="panel-heading">Login</div>
    <div class="panel-body">
     <form method="post">
      <p class="text-danger"><?php echo $message; ?></p>
      <div class="form-group">
       <label>Enter Username</label>
       <input type="text" name="username" class="form-control" required />
      </div>
      <div class="form-group">
       <label>Enter Password</label>
       <input type="password" name="password" class="form-control" required />
      </div>
      <div class="form-group">
       <input type="submit" name="login" class="btn btn-info" value="Login" />
      </div>
      <div align="center">
       <a href="register.php">Register</a>
      </div>
     </form>
    </div>
   </div>
  </div>
    </body>  
</html>


index.php


If system is validated user information, and it is correct then page will be redirect to index.php page. From this page user can share his or her post. User can view his or her post along with post of follow user by login user. On index page user can view all user list with follow and unfollow button. Most of all operation of follow and unfollow system like post new post, comment on other user post, follow and unfollow other user, repost follow yser post will be done on this page. This page will be view to only login user.


<!--
//index.php
!-->

<?php

include('database_connection.php');

session_start();

if(!isset($_SESSION['user_id']))
{
    header('location:login.php');
}

?>

<html>  
    <head>  
        <title>Twitter Like Follow Unfollow System in PHP using Ajax jQuery</title>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.form/4.2.2/jquery.form.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-3-typeahead/4.0.2/bootstrap3-typeahead.min.js"></script>
        <style>

        .main_division
        {
            position: relative;
            width: 100%;
            height: auto;
            background-color: #FFF;
            border: 1px solid #CCC;
            border-radius: 3px;
        }
        #sub_division
        {
            width: 100%;
            height: auto;
            min-height: 80px;
            overflow: auto;
            padding:6px 24px 6px 12px;
        }
        .image_upload
        {
            position: absolute;
            top:0px;
            right:16px;
        }
        .image_upload > form > input
        {
            display: none;
        }

        .image_upload img
        {
            width: 24px;
            cursor: pointer;
        }

        </style>
    </head>  
    <body>  
        <div class="container">
   <?php
            include('menu.php');
            ?>
            <div class="row">
                <div class="col-md-8">
                    <div class="panel panel-default">
                        <div class="panel-heading">
                            <div class="row">
                                <div class="col-md-8">
                                    <h3 class="panel-title">Start Write Here</h3>
                                </div>
                                <div class="col-md-4">
                                    <div class="image_upload">
                                        <form id="uploadImage" method="post" action="upload.php">
                                            <label for="uploadFile"><img src="upload.png" /></label>
                                            <input type="file" name="uploadFile" id="uploadFile" accept=".jpg, .png, .mp4" />
                                        </form>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="panel-body">
                            <form method="post" id="post_form">
                                <div class="form-group" id="dynamic_field">
                                    <textarea name="post_content" id="post_content" maxlength="160" class="form-control" placeholder="Write your short story"></textarea>
                                </div>
                                <div id="link_content"></div>
                                <div class="form-group" align="right">
                                    <input type="hidden" name="action" value="insert" />
                                    <input type="hidden" name="post_type" id="post_type" value="text" />
                                    <input type="submit" name="share_post" id="share_post" class="btn btn-primary" value="Share" />
                                </div>
                            </form>
                        </div>
                    </div>
                    <div class="panel panel-default">
                        <div class="panel-heading">
                            <h3 class="panel-title">Trending Now</h3>
                        </div>
                        <div class="panel-body">
                            <div id="post_list">

                            </div>
                        </div>
                    </div>
                </div>
                <div class="col-md-4">
                    <div class="panel panel-default">
                        <div class="panel-heading">
                            <h3 class="panel-title">User List</h3>
                        </div>
                        <div class="panel-body">
                            <div id="user_list"></div>
                        </div>
                    </div>
                </div>
            </div>
  </div>
    </body>  
</html>

<?php

include('jquery.php');

?>


jquery.php



<script>  
$(document).ready(function(){
 
 $('#post_form').on('submit', function(event){
        event.preventDefault();
        if($('#post_type').val() == 'upload')
        {
            $('#post_content').val($('#sub_division').html());
        }

        if($('#post_type').val() == 'link')
        {
            $('#post_content').val($('#link_content').html());
            $('#link_content').css('padding', '0');
            $('#link_content').css('background-color', '');
            $('#link_content').css('margin-bottom', '0');
        }

        if($('#post_content').val() == '')
        {
            alert('Enter Story Content');
        }
        else
        {
            var form_data = $(this).serialize();
            $.ajax({
                url:"action.php",
                method:"POST",
                data:form_data,
                beforeSend:function()
                {
                    $('#share_post').attr('disabled', 'disabled');  
                },
                success:function(data)
                {
                    //alert('Post has been shared');
                    $('#dynamic_field').html('<textarea name="post_content" id="post_content" maxlength="160" class="form-control" placeholder="Write your short story"></textarea>');
                    $('#post_type').val('text');
                    $('#post_form')[0].reset();
                    fetch_post();
                    $('#link_content').html('');
                    $('#share_post').attr('disabled', false);
                }
            })
        }
    });

    fetch_post();

    function fetch_post()
    {
       var action = 'fetch_post';
       $.ajax({
            url:'action.php',
            method:"POST",
            data:{action:action},
            success:function(data)
            {
                $('#post_list').html(data);
            }
       })
    }

    fetch_user();

    function fetch_user()
    {
        var action = 'fetch_user';
        $.ajax({
            url:"action.php",
            method:"POST",
            data:{action:action},
            success:function(data)
            {
                $('#user_list').html(data);
            }
        });
    }

    $(document).on('click', '.action_button', function(){
        var sender_id = $(this).data('sender_id');
        var action = $(this).data('action');
        $.ajax({
            url:"action.php",
            method:"POST",
            data:{sender_id:sender_id, action:action},
            success:function(data)
            {
                fetch_user();
                fetch_post();
            }
        })
    });

    var post_id;
    var user_id;

    $(document).on('click', '.post_comment', function(){
        post_id = $(this).attr('id');
        user_id = $(this).data('user_id');
        var action = 'fetch_comment';
        $.ajax({
            url:"action.php",
            method:"POST",
            data:{post_id:post_id, user_id:user_id, action:action},
            success:function(data){
                $('#old_comment'+post_id).html(data);
                $('#comment_form'+post_id).slideToggle('slow');
            }
        })
        
    });

    $(document).on('click', '.submit_comment', function(){
        var comment = $('#comment'+post_id).val();
        var action = 'submit_comment';
        var receiver_id = user_id;
        if(comment != '')
        {
            $.ajax({
                url:"action.php",
                method:"POST",
                data:{post_id:post_id,receiver_id:receiver_id,comment:comment,action:action},
                success:function(data)
                {
                    $('#comment_form'+post_id).slideUp('slow');
                    fetch_post();
                }
            })
        }
    });

    $(document).on('click', '.repost', function(){
        var post_id = $(this).data('post_id');
        var action = 'repost';
        $.ajax({
            url:"action.php",
            method:"POST",
            data:{post_id:post_id, action:action},
            success:function(data)
            {
                alert(data);
                fetch_post();
            }
        })
    });

    $(document).on('click', '.like_button', function(){
        var post_id = $(this).data('post_id');
        var action = 'like';
        $.ajax({
            url:"action.php",
            method:"POST",
            data:{post_id:post_id, action:action},
            success:function(data)
            {
                alert(data);
                fetch_post();
            }
        })
    });

    $('body').tooltip({
        selector: '.like_button',
        title: fetch_post_like_user_list,
        html: true,
        placement: 'right'
    });

    function fetch_post_like_user_list()
    {
        var fetch_data = '';
        var element = $(this);
        var post_id = element.data('post_id');
        var action = 'like_user_list';
        $.ajax({
            url:"action.php",
            method:"POST",
            async: false,
            data:{post_id:post_id, action:action},
            success:function(data)
            {
                fetch_data = data;
            }
        });
        return fetch_data;
    }

    $('#uploadFile').on('change', function(event){
        var html = '<div class="main_division">';
        html += '<div id="sub_division" contenteditable class="form-control"></div></div>';
        html += '<input type="hidden" name="post_content" id="post_content" />';
        $('#post_type').val('upload');
        $('#dynamic_field').html(html);
        $('#uploadImage').ajaxSubmit({
            target :'#sub_division',
            resetForm :true
        });
    });

    $(document).on('keyup', '#post_content', function(){
        var check_content = $('#post_content').val();
        var check_url = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;

        var if_url = check_content.match(check_url);

        if(if_url)
        {
            $('#link_content').css('padding', '16px');
            $('#link_content').css('background-color', '#f9f9f9');
            $('#link_content').css('margin-bottom', '16px');
            $('#link_content').html('<h4>Fetching...</h4>');
            $('#post_type').val('link');
            var action = 'fetch_link_content';
            $.ajax({
                url:"action.php",
                method:"POST",
                data:{action:action, url:if_url},
                success:function(data)
                {
                    var title = $(data).filter("meta[property='og:title']").attr('content');
                    var description = $(data).filter("meta[property='og:description']").attr('content');

                    var image = $(data).filter("meta[property='og:image']").attr('content');

                    if(title == undefined)
                    {
                        title = $(data).filter("meta[name='twitter:title']").attr('content');
                    }

                    if(description == undefined)
                    {
                        description = $(data).filter("meta[name='twitter:description']").attr('content');
                    }

                    if(image == undefined)
                    {
                        image = $(data).filter("meta[name='twitter:image']").attr('content');
                    }

                    var output = '<p><a href="'+if_url[0]+'">'+if_url[0]+'</a></p>';

                    output += '<img src="'+image+'" class="img-responsive img-thumbnail" />';
                    output += '<h3><b>'+title+'</b></h3>';
                    output += '<p>'+description+'</p>';
                    $('#link_content').html(output);
                }
            })
        }
        else
        {
            $('#link_content').html('');
            $('#link_content').css('padding', '0');
            $('#link_content').css('background-color', '');
            $('#link_content').css('margin-bottom', '');
            return false;
        }
    });

    $('#view_notification').click(function(){
        var action = 'update_notification_status';
        $.ajax({
            url:"action.php",
            method:"post",
            data:{action:action},
            success:function(data)
            {
                $('#total_notification').remove();
            }
        })
    });
 
});  
</script>


menu.php


This file is used for make dynamic menu, here user name will be display by using $_SESSION varibale. Here in this we have add two menu for go to profile page and logout page.


<br />
   <nav class="navbar navbar-inverse">
    <div class="container-fluid">
     <div class="navbar-header">
      <a class="navbar-brand" href="index.php">Webslesson</a>
     </div>
     <ul class="nav navbar-nav navbar-right">
      <li>
       <input type="text" name="search_user" id="search_user" class="form-control input-sm" placeholder="Search User" autocomplete="off" style="margin-top: 10px; width: 400px; margin-right:180px;" />
      </li>
      <li class="dropdown">
       <a class="dropdown-toggle" data-toggle="dropdown" href="#" id="view_notification">Notification
       <?php
       $total_notification = Count_notification($connect, $_SESSION["user_id"]);

       if($total_notification > 0)
       {
        echo '<span class="label label-danger" id="total_notification">'.$total_notification.'</span>';

       }


       ?>
        <span class="caret"></span></a>
        <ul class="dropdown-menu">
        <?php
        echo Load_notification($connect, $_SESSION["user_id"]);

        ?>

        </ul>
       </a>
      </li>
      <li class="dropdown">
       <a class="dropdown-toggle" data-toggle="dropdown" href="#"><?php echo $_SESSION['username']; ?>
       <span class="caret"></span></a>
       <ul class="dropdown-menu">
        <li><a href="profile.php">Profile</a></li>
        <li><a href="logout.php">Logout</a></li>
       </ul>
      </li>
     </ul>
    </div>
   </nav>

   <script type="text/javascript">

    $(document).ready(function(){
     $('#search_user').typeahead({
      source:function(query, result)
      {
       $('.typeahead').css('position', 'absolute');
       $('.typeahead').css('top', '45px');
       var action = 'search_user';
       $.ajax({
        url:"action.php",
        method:"POST",
        data:{query:query, action:action},
        dataType:"json",
        success:function(data)
        {
         result($.map(data, function(item){
          return item;
         }));
        }
       })
      }
     });

     $(document).on('click', '.typeahead li', function(){
      var search_query = $(this).text();
      window.location.href="wall.php?data="+search_query;
     });
    });

   </script>


logout.php


If user want to logout from dynamic follow unfollow application, so when user click on logout link then page will redirect to this page, and on this page all $_SESSION variable will be destroy using session_destroy() function.


<?php

//logout.php

session_start();

session_destroy();

header('location:login.php');

?>


profile.php


This file is used for edit user profile details in follow unfollow application by using PHP. Here user not only edit their profile details like username, password, name and short bio but also user can change profile image by upload image file under images folder. This image and user name will be display to other user.


<!--
//profile.php
!-->

<?php

include('database_connection.php');

session_start();

if(!isset($_SESSION['user_id']))
{
 header('location:login.php');
}

$message = '';

if(isset($_POST['edit_profile']))
{
 $file_name = '';
 if(isset($_POST['profile_image']))
 {
  $file_name = $_POST['profile_image'];
 }

 if($_FILES['profile_image']['name'] != '')
 {
  if($file_name != '')
  {
   unlink('images/'.$file_name);
  }
  $image_name = explode(".", $_FILES['profile_image']['name']);
  $extension = end($image_name);
  $temporary_location = $_FILES['profile_image']['tmp_name'];
  $file_name = rand() . '.' . strtolower($extension);
  $location = 'images/' . $file_name;
  move_uploaded_file($temporary_location, $location);
 }
 $check_query = "
 SELECT * FROM tbl_twitter_user WHERE username = :username AND user_id != :user_id
 ";
 $statement = $connect->prepare($check_query);
 $statement->execute(
  array(
   ':username'  =>  trim($_POST["username"]),
   ':user_id'  =>  $_SESSION["user_id"]
  )
 );
 $total_row = $statement->rowCount();
 if($total_row > 0)
 {
  $message = '<div class="alert alert-danger">Username Already Exists</div>';
 }
 else
 {
  $data = array(
   ':username'   => trim($_POST["username"]),
   ':name'    => trim($_POST["name"]),
   ':profile_image' => $file_name,
   ':bio'    => trim($_POST["bio"]),
   ':user_id'   => $_SESSION["user_id"]
  );
  if($_POST['password'] != '')
  {
   $data[] = array(
    ':password'  => password_hash($_POST["password"], PASSWORD_DEFAULT)
   );
   $query = '
   UPDATE tbl_twitter_user SET username = :username, password = :password, name = :name, profile_image = :profile_image, bio = :bio WHERE user_id = :user_id
   ';
  }
  else
  {
   $query = '
   UPDATE tbl_twitter_user SET username = :username, name = :name, profile_image = :profile_image, bio = :bio WHERE user_id = :user_id
   ';
  }
  $statement = $connect->prepare($query);
  if($statement->execute($data))
  {
   $message = '<div class="alert alert-success">Profile Updated</div>';
  }
 }
}



$query = "SELECT * FROM tbl_twitter_user WHERE user_id = '".$_SESSION["user_id"]."'";

$statement = $connect->prepare($query);

$statement->execute();

$result = $statement->fetchAll();

?>

<html>  
    <head>  
        <title>Twitter Like Follow Unfollow System in PHP using Ajax jQuery</title>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.form/4.2.2/jquery.form.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
    </head>  
    <body>  
        <div class="container">
   <?php 
   include('menu.php');
   ?>
   <div class="row">
    <div class="col-md-3">
    
    </div>
    <div class="col-md-6">
     <div class="panel panel-default">
      <div class="panel-heading">
       <h3 class="panel-title">Edit Profile</h3>
      </div>
      <div class="panel-body">
       <?php
       foreach($result as $row)
       {
        echo $message;
       ?>
       <form method="post" enctype="multipart/form-data">
        <div class="form-group">
         <label>Username</label>
         <input type="text" name="username" id="username" pattern="^[a-zA-Z0-9_.-]*$" required class="form-control" value="<?php echo $row["username"];?>" />
        </div>
        <div class="form-group">
         <label>Password</label>
         <input type="password" name="password" id="password" class="form-control" />
        </div>
        <div class="form-group">
         <label>Name</label>
         <input type="text" name="name" id="name" class="form-control" required value="<?php echo $row["name"]; ?>" />
        </div>
        <div class="form-group">
         <label>Profile Image</label>
         <input type="file" name="profile_image" id="profile_image" accept="image/*" />
         <?php
         if($row["profile_image"] != '')
         {
          echo '<img src="images/'.$row["profile_image"].'" class="img-thumbnail" width="150" />';
          echo '<input type="hidden" name="profile_image" value="'.$row["profile_image"].'" />';
         }
         ?>
        </div>
        <div class="form-group">
         <label>Short Bio</label>
         <textarea name="bio" id="bio" class="form-control"><?php echo $row["bio"]; ?></textarea>
        </div>
        <div class="form-group">
         <input type="submit" name="edit_profile" id="edit_profile" class="btn btn-primary" value="Save" />
        </div>
       </form>
       <?php
       }
       ?>
      </div>
     </div>
    </div>
    <div class="col-md-3">
    
    </div>
   </div>
  </div>
    </body>  
</html>


action.php


This file is used for perform all core operation of Insert Post, Fetch post data, fetch user data and make follow unfollow button in PHP Follow Unfollow system. This file will received request for all above operation.


<?php

//action.php

include('database_connection.php');

session_start();

if(isset($_POST['action']))
{
 $output = '';
 if($_POST['action'] == 'insert')
 {
  $data = array(
   ':user_id'   => $_SESSION["user_id"],
   ':post_content'  => $_POST["post_content"],
   ':post_datetime' => date("Y-m-d") . ' ' . date("H:i:s", STRTOTIME(date('h:i:sa')))
  );
  $query = "
  INSERT INTO tbl_samples_post 
  (user_id, post_content, post_datetime) 
  VALUES (:user_id, :post_content, :post_datetime)
  ";

  $statement = $connect->prepare($query);
  $statement->execute($data);

  $notification_query = "
  SELECT receiver_id FROM tbl_follow 
  WHERE sender_id = '".$_SESSION["user_id"]."'
  ";

  $statement = $connect->prepare($notification_query);

  $statement->execute();

  $notification_result = $statement->fetchAll();

  foreach($notification_result as $notification_row)
  {
   $notification_text= '<b>' . Get_user_name($connect, $_SESSION["user_id"]) . '</b> has share new post';

   $insert_query = "
   INSERT INTO tbl_notification 
   (notification_receiver_id, notification_text, read_notification) 
   VALUES ('".$notification_row['receiver_id']."', '".$notification_text."', 'no')
   ";

   $statement = $connect->prepare($insert_query);

   $statement->execute();
  }
 }

 if($_POST['action'] == 'fetch_post')
 {
  $query = "
  SELECT * FROM tbl_samples_post 
  INNER JOIN tbl_twitter_user ON tbl_twitter_user.user_id = tbl_samples_post.user_id 
  LEFT JOIN tbl_follow ON tbl_follow.sender_id = tbl_samples_post.user_id 
  WHERE tbl_follow.receiver_id = '".$_SESSION["user_id"]."' OR tbl_samples_post.user_id = '".$_SESSION["user_id"]."' 
  GROUP BY tbl_samples_post.post_id 
  ORDER BY tbl_samples_post.post_id DESC
  ";
  $statement = $connect->prepare($query);
  $statement->execute();
  $result = $statement->fetchAll();
  $total_row = $statement->rowCount();
  if($total_row > 0)
  {
   foreach($result as $row)
   {
    $profile_image = '';
    if($row['profile_image'] != '')
    {
     $profile_image = '<img src="images/'.$row["profile_image"].'" class="img-thumbnail img-responsive" />';
    }
    else
    {
     $profile_image = '<img src="images/user.jpg" class="img-thumbnail img-responsive" />';
    }

    $repost = 'disabled';
    if($row['user_id'] != $_SESSION['user_id'])
    {
     $repost = '';
    }
    $output .= '
    <div class="jumbotron" style="padding:24px 30px 24px 30px">
     <div class="row">
      <div class="col-md-2">
       '.$profile_image.'
      </div>
      <div class="col-md-8">
       <h3><b>@'.$row["username"].'</b></h3>
       <p>'.$row["post_content"].'<br /><br />
       <button type="button" class="btn btn-link post_comment" id="'.$row["post_id"].'" data-user_id="'.$row["user_id"].'">'.count_comment($connect, $row["post_id"]).' Comment</button>
       <button type="button" class="btn btn-danger repost" data-post_id="'.$row["post_id"].'" '.$repost.'><span class="glyphicon glyphicon-retweet"></span>&nbsp;&nbsp;'.count_retweet($connect, $row["post_id"]).'</button>


       <button type="button" class="btn btn-link like_button" data-post_id="'.$row["post_id"].'"><span class="glyphicon glyphicon-thumbs-up"></span> Like '.count_total_post_like($connect, $row["post_id"]).'</button>


       </p>
       <div id="comment_form'.$row["post_id"].'" style="display:none;">
        <span id="old_comment'.$row["post_id"].'"></span>
        <div class="form-group">
         <textarea name="comment" class="form-control" id="comment'.$row["post_id"].'"></textarea>
        </div>
        <div class="form-group" align="right">
         <button type="button" name="submit_comment" class="btn btn-primary btn-xs submit_comment">Comment</button>
        </div>
       </div>
      </div>
     </div>
    </div>
    ';
   }
  }
  else
  {
   $output = '<h4>No Post Found</h4>';
  }
  echo $output;
 }
 if($_POST['action'] == 'fetch_user')
 {
  $query = "
  SELECT * FROM tbl_twitter_user 
  WHERE user_id != '".$_SESSION["user_id"]."' 
  ORDER BY user_id DESC 
  LIMIT 15
  ";
  $statement = $connect->prepare($query);
  $statement->execute();
  $result = $statement->fetchAll();
  foreach($result as $row)
  {
   $profile_image = '';
   if($row['profile_image'] != '')
   {
    $profile_image = '<img src="images/'.$row["profile_image"].'" class="img-thumbnail img-responsive" />';
   }
   else
   {
    $profile_image = '<img src="images/user.jpg" class="img-thumbnail img-responsive" />';
   }
   $output .= '
   <div class="row">
    <div class="col-md-4">
     '.$profile_image.'
    </div>
    <div class="col-md-8">
     <h4><b>@'.$row["username"].'</b></h4>
     '.make_follow_button($connect, $row["user_id"], $_SESSION["user_id"]).'
     <span class="label label-success"> '.$row["follower_number"].' Followers</span>
    </div>
   </div>
   <hr />
   ';
  }
  echo $output;
 }

 if($_POST['action'] == 'follow')
 {
  $query = "
  INSERT INTO tbl_follow 
  (sender_id, receiver_id) 
  VALUES ('".$_POST["sender_id"]."', '".$_SESSION["user_id"]."')
  ";
  $statement = $connect->prepare($query);
  if($statement->execute())
  {
   $sub_query = "
   UPDATE tbl_twitter_user SET follower_number = follower_number + 1 WHERE user_id = '".$_POST["sender_id"]."'
   ";
   $statement = $connect->prepare($sub_query);
   $statement->execute();

   $notification_text = '<b>' . Get_user_name($connect, $_SESSION["user_id"]) . '</b> has follow you.';

   $insert_query = "
   INSERT INTO tbl_notification 
   (notification_receiver_id, notification_text, read_notification) 
   VALUES ('".$_POST["sender_id"]."', '".$notification_text."', 'no')
   ";

   $statement = $connect->prepare($insert_query);
   $statement->execute();
  }

 }

 if($_POST['action'] == 'unfollow')
 {
  $query = "
  DELETE FROM tbl_follow 
  WHERE sender_id = '".$_POST["sender_id"]."' 
  AND receiver_id = '".$_SESSION["user_id"]."'
  ";
  $statement = $connect->prepare($query);
  if($statement->execute())
  {
   $sub_query = "
   UPDATE tbl_twitter_user 
   SET follower_number = follower_number - 1 
   WHERE user_id = '".$_POST["sender_id"]."'
   ";
   $statement = $connect->prepare($sub_query);
   $statement->execute();

   $notification_text = '<b>' . Get_user_name($connect, $_SESSION["user_id"]) . '</b> has unfollow you.';

   $insert_query = "
   INSERT INTO tbl_notification 
   (notification_receiver_id, notification_text, read_notification) 
   VALUES ('".$_POST["sender_id"]."', '".$notification_text."', 'no')
   ";
   $statement = $connect->prepare($insert_query);

   $statement->execute();
  }
 }

 if($_POST["action"] == 'submit_comment')
 {
  $data = array(
   ':post_id'  => $_POST["post_id"],
   ':user_id'  => $_SESSION["user_id"],
   ':comment'  => $_POST["comment"],
   ':timestamp' => date("Y-m-d") . ' ' . date("H:i:s", STRTOTIME(date('h:i:sa')))
  );
  $query = "
  INSERT INTO tbl_comment 
  (post_id, user_id, comment, timestamp) 
  VALUES (:post_id, :user_id, :comment, :timestamp)
  ";
  $statement = $connect->prepare($query);
  $statement->execute($data);

  $notification_query = "
  SELECT user_id, post_content FROM tbl_samples_post 
  WHERE post_id = '".$_POST["post_id"]."'
  ";

  $statement = $connect->prepare($notification_query);

  $statement->execute();

  $notification_result = $statement->fetchAll();

  foreach($notification_result as $notification_row)
  {
   $notification_text = '<b>'.Get_user_name($connect, $_SESSION["user_id"]).'</b> has comment on your post - "'.strip_tags(substr($notification_row["post_content"], 0, 30)).'..."';

   $insert_query = "
   INSERT INTO tbl_notification 
   (notification_receiver_id, notification_text, read_notification) 
   VALUES ('".$notification_row['user_id']."', '".$notification_text."', 'no')
   ";

   $statement = $connect->prepare($insert_query);
   $statement->execute();
  }


 }
 if($_POST["action"] == "fetch_comment")
 {
  $query = "
  SELECT * FROM tbl_comment 
  INNER JOIN tbl_twitter_user 
  ON tbl_twitter_user.user_id = tbl_comment.user_id 
  WHERE post_id = '".$_POST["post_id"]."' 
  ORDER BY comment_id ASC
  ";
  $statement = $connect->prepare($query);
  $output = '';
  if($statement->execute())
  {
   $result = $statement->fetchAll();
   foreach($result as $row)
   {
    $profile_image = '';
    if($row['profile_image'] != '')
    {
     $profile_image = '<img src="images/'.$row["profile_image"].'" class="img-thumbnail img-responsive img-circle" />';
    }
    else
    {
     $profile_image = '<img src="images/user.jpg" class="img-thumbnail img-responsive img-circle" />';
    }
    $output .= '
    <div class="row">
     <div class="col-md-2">
     '.$profile_image.' 
     </div>
     <div class="col-md-10" style="margin-top:16px; padding-left:0">
      <small><b>@'.$row["username"].'</b><br />
      '.$row["comment"].'
      </small>
     </div>
    </div>
    <br />
    ';
   }
  }
  echo $output;
 }

 if($_POST['action'] == 'repost')
 {
  $query = "
  SELECT * FROM tbl_repost 
  WHERE post_id = '".$_POST["post_id"]."' 
  AND user_id = '".$_SESSION["user_id"]."'
  ";
  $statement = $connect->prepare($query);
  $statement->execute();
  $total_row = $statement->rowCount();
  if($total_row > 0)
  {
   echo 'You have already repost this post';
  }
  else
  {
   $query1 = "
   INSERT INTO tbl_repost 
   (post_id, user_id) 
   VALUES ('".$_POST["post_id"]."', '".$_SESSION["user_id"]."')
   ";
   $statement = $connect->prepare($query1);
   if($statement->execute())
   {
    $query2 = "
    SELECT * FROM tbl_samples_post 
    WHERE post_id = '".$_POST["post_id"]."'
    ";
    $statement = $connect->prepare($query2);
    if($statement->execute())
    {
     $result = $statement->fetchAll();
     $post_content = '';
     foreach($result as $row)
     {
      $post_content = $row['post_content'];
     }
     $query3 = "
     INSERT INTO tbl_samples_post 
     (user_id, post_content, post_datetime) 
     VALUES ('".$_SESSION["user_id"]."', '".$post_content."', '".date("Y-m-d") . ' ' . date("H:i:s", STRTOTIME(date('h:i:sa')))."')
     ";
     $statement = $connect->prepare($query3);
     if($statement->execute())
     {

      $notification_query = "
      SELECT user_id, post_content FROM tbl_samples_post 
      WHERE post_id = '".$_POST["post_id"]."'
      ";

      $statement = $connect->prepare($notification_query);

      $statement->execute();

      $notification_result = $statement->fetchAll();

      foreach($notification_result as $notification_row)
      {
       $notification_text = '<b>'.Get_user_name($connect, $_SESSION["user_id"]).'</b> has repost your post - "'.strip_tags(substr($notification_row["post_content"], 0, 30)).'..."';

       $insert_query = "
       INSERT INTO tbl_notification 
       (notification_receiver_id, notification_text, read_notification) 
       VALUES ('".$notification_row['user_id']."', '".$notification_text."', 'no')
       ";
       $statement = $connect->prepare($insert_query);
       $statement->execute();
      }

      echo 'Repost done successfully';
     }
    }
   }
  }
 }

 if($_POST["action"] == "like")
 {
  $query = "
  SELECT * FROM tbl_like 
  WHERE post_id = '".$_POST["post_id"]."' 
  AND user_id = '".$_SESSION["user_id"]."'
  ";
  $statement = $connect->prepare($query);
  $statement->execute();

  $total_row = $statement->rowCount();

  if($total_row > 0)
  {
   echo 'You have already like this post';
  }
  else
  {
   $insert_query = "
   INSERT INTO tbl_like 
   (user_id, post_id) 
   VALUES ('".$_SESSION["user_id"]."', '".$_POST["post_id"]."')
   ";

   $statement = $connect->prepare($insert_query);

   $statement->execute();

   $notification_query = "
   SELECT user_id, post_content FROM tbl_samples_post 
   WHERE post_id = '".$_POST["post_id"]."'
   ";

   $statement = $connect->prepare($notification_query);

   $statement->execute();

   $notification_result = $statement->fetchAll();

   foreach($notification_result as $notification_row)
   {
    $notification_text = '
    <b>' . Get_user_name($connect, $_SESSION["user_id"]) . '</b> has like your post - "'.strip_tags(substr($notification_row["post_content"], 0, 30)).'..."
    ';

    $insert_query = "
    INSERT INTO tbl_notification 
     (notification_receiver_id, notification_text, read_notification) 
     VALUES ('".$notification_row['user_id']."', '".$notification_text."', 'no')
    ";

    $statement = $connect->prepare($insert_query);
    $statement->execute();
   }

   echo 'Like';
  }

 }

 if($_POST["action"] == "like_user_list")
 {
  $query = "
  SELECT * FROM tbl_like 
  INNER JOIN tbl_twitter_user 
  ON tbl_twitter_user.user_id = tbl_like.user_id 
  WHERE tbl_like.post_id = '".$_POST["post_id"]."'
  ";

  $statement = $connect->prepare($query);

  $statement->execute();

  $result = $statement->fetchAll();

  foreach($result as $row)
  {
   $output .= '
   <p>'.$row["username"].'</p>
   ';
  }

  echo $output;
 }

 if($_POST["action"] == "fetch_link_content")
 {
  echo file_get_contents($_POST["url"][0]);
 }

 if($_POST["action"] == "update_notification_status")
 {
  $query = "
  UPDATE tbl_notification 
  SET read_notification = 'yes' 
  WHERE notification_receiver_id = '".$_SESSION["user_id"]."'
  ";

  $statement = $connect->prepare($query);

  $statement->execute();
 }

 if($_POST["action"] == "search_user")
 {
  $query = "
  SELECT username, profile_image FROM tbl_twitter_user 
  WHERE username LIKE '%".$_POST["query"]."%' 
  AND user_id != '".$_SESSION["user_id"]."'
  ";
  $statement = $connect->prepare($query);
  $statement->execute();
  $result = $statement->fetchAll();
  foreach($result as $row)
  {
   $data[] = $row["username"];
  }
  echo json_encode($data);
 }
}

?>


upload.php



?php

//upload.php

if(!empty($_FILES))
{
 $file_extension = strtolower(pathinfo($_FILES["uploadFile"]["name"], PATHINFO_EXTENSION));

 $new_file_name = rand() . '.' . $file_extension;

 $source_path = $_FILES["uploadFile"]["tmp_name"];

 $target_path = 'images/' . $_FILES["uploadFile"]["name"];

 if(move_uploaded_file($source_path, $target_path))
 {
  if($file_extension == 'jpg' || $file_extension == 'png')
  {
   echo '<p><img src="'.$target_path.'" class="img-responsive img-thumbnail" /></p><br />';
  }

  if($file_extension == 'mp4')
  {
   echo '
   <div class="embed-responsive embed-responsive-16by9">
    <video class="embed-responsive-item" controls="controls" src="'.$target_path.'"></video>
   </div>
   <br />
   ';
  }
 }
}

?>


wall.php



<!--
//wall.php
!-->

<?php

include('database_connection.php');

session_start();

if(!isset($_SESSION['user_id']))
{
 header('location:login.php');
}

$query = "
SELECT * FROM tbl_samples_post 
INNER JOIN tbl_twitter_user ON tbl_twitter_user.user_id = tbl_samples_post.user_id 
WHERE tbl_twitter_user.username = '".$_GET["data"]."' 
GROUP BY tbl_samples_post.post_id 
ORDER BY tbl_samples_post.post_id DESC
";

$statement = $connect->prepare($query);

$statement->execute();

$total_row = $statement->rowCount();

$user_id = Get_user_id($connect, $_GET["data"]);

?>

<html>  
    <head>  
        <title>Twitter Like Follow Unfollow System in PHP using Ajax jQuery</title>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.form/4.2.2/jquery.form.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-3-typeahead/4.0.2/bootstrap3-typeahead.min.js"></script>
    </head>  
    <body>  
        <div class="container">
   <?php
   include('menu.php');
   ?>
   <div class="row">
    <?php
    if($total_row > 0)
    {
     $result = $statement->fetchAll();
    ?> 
    <div class="col-md-9">
     <div class="panel panel-default">
      <div class="panel-heading">
       <div class="row">
        <div class="col-md-6">
         <h3 class="panel-title"><?php echo '<b>'.$_GET["data"].'</b>';?> Post Details</h3>
        </div>
        <div class="col-md-6" align="right">
         <?php
         if($user_id != $_SESSION["user_id"])
         {
          echo make_follow_button($connect, $user_id, $_SESSION["user_id"]);
         }
         ?>
        </div>
       </div>
      </div>
      <div class="panel-body">
      <?php
      foreach($result as $row)
      {
       $profile_image = '';
       if($row['profile_image'] != '')
       {
        $profile_image = '<img src="images/'.$row["profile_image"].'" class="img-thumbnail img-responsive" />';
       }
       else
       {
        $profile_image = '<img src="images/user.jpg" class="img-thumbnail img-responsive" />';
       }

       $repost = 'disabled';

       if($row['user_id'] != $_SESSION['user_id'])
       {
        $repost = '';
       }

       echo '
       <div class="jumbotron" style="padding:24px 30px 24px 30px">
        <div class="row">
         <div class="col-md-2">
          '.$profile_image.'
         </div>
         <div class="col-md-10">
          <h3><b>@'.$row["username"].'</b></h3>
          <p>'.$row["post_content"].'<br /><br />
          <button type="button" class="btn btn-link post_comment" id="'.$row["post_id"].'" data-user_id="'.$row["user_id"].'">'.count_comment($connect, $row["post_id"]).' Comment</button>
          <button type="button" class="btn btn-danger repost" data-post_id="'.$row["post_id"].'" '.$repost.'><span class="glyphicon glyphicon-retweet"></span>&nbsp;&nbsp;'.count_retweet($connect, $row["post_id"]).'</button>
          <button type="button" class="btn btn-link like_button" data-post_id="'.$row["post_id"].'"><span class="glyphicon glyphicon-thumbs-up"></span> Like '.count_total_post_like($connect, $row["post_id"]).'</button>
          </p>
          <div id="comment_form'.$row["post_id"].'" style="display:none;">
           <span id="old_comment'.$row["post_id"].'"></span>
           <div class="form-group">
            <textarea name="comment" class="form-control" id="comment'.$row["post_id"].'"></textarea>
           </div>
           <div class="form-group" align="right">
            <button type="button" name="submit_comment" class="btn btn-primary btn-xs submit_comment" data-post_id="'.$row["post_id"].'">Comment</button>
           </div>
          </div>
         </div>
        </div>
       </div>
       ';
      }
      ?>
      </div>
     </div>
     
    </div>
    <div class="col-md-3">
     <div class="panel panel-default">
      <div class="panel-heading">
       <h3 class="panel-title"><?php echo $_GET["data"]; ?> Followers</h3>
      </div>
      <div class="panel-body">
      <?php

      $follower_query = "
      SELECT * FROM tbl_twitter_user 
       INNER JOIN tbl_follow 
       ON tbl_follow.receiver_id = tbl_twitter_user.user_id 
       WHERE tbl_follow.sender_id = '".$user_id."'
      ";

      $statement = $connect->prepare($follower_query);

      $statement->execute();

      $follower_result = $statement->fetchAll();

      foreach($follower_result as $follower_row)
      {
       $profile_image = '';
       if($follower_row['profile_image'] != '')
       {
        $profile_image = '<img src="images/'.$follower_row["profile_image"].'" class="img-thumbnail img-thumbnail" />';
       }
       else
       {
        $profile_image = '<img src="images/user.jpg" class="img-thumbnail img-responsive" />';
       }

       echo '
       <div class="row">
        <div class="col-md-4">
         '.$profile_image.'
        </div>
        <div class="col-md-8">
         <h4><b>@<a href="wall.php?data='.$follower_row["username"].'">'.$follower_row["username"].'</a></b></h4>
        </div>
       </div>
       <hr />
       ';
       
      }

      ?>
      </div>
     </div>
    </div>
    <?php
    }
    else
    {
     echo '<h3 align="center">No Post Found</h3>';
    }
    ?>
   </div>
  </div>
    </body>  
</html>

<?php
include('jquery.php');
?>


This is our PHP Ajax Follow Unfollow System source code, If there is any new feature has been added then we will add updated source code under this post.