PHP React Nested Comment System With Reply And MySQL

Today, all websites have a comment system, which is very important for blog websites. By using the comment system, users can register their opinions on the desired article or product on the website. PHP comment system is widely used in web development to allow users to leave comments on websites or blog posts. These systems provide an interactive and engaging way for visitors to express their opinions, ask questions, and engage in discussions.

In this article, we want to create and implement the comment system in PHP and React. Other users can answer throughout the comment system.

The user side of the comment system is designed by ReactJS, but in a part of this article, we will show it only using PHP. This system uses the MySQL database to store comments, which will be displayed using PHP.

As far as possible, we have tried to create an advanced comment system using MySQL, PHP, and React. This system supports multi-level comments so that each user can register their own comment for another user’s comment and is displayed in a nested format.

In the comment system using PHP and React, on the React side, all data is sent and received using AJAX technology. PHP sends this data to the server to extract its information from the MySQL database. Stay with us to see how to create and implement a nested comment system using PHP, React, MySQL, and AJAX with a reply.

What is a comment system?

A comment system is a type of software that allows users to leave comments, feedback, or reviews on a website or application. This type of system is commonly used on blogs, forums, and other interactive websites. Comment systems often include features such as user registration, moderation, and filtering to ensure that the comments are appropriate and useful. Comment systems can also be used to create a sense of community and engagement among users.

What is PHP?

PHP is a server-side scripting language that we will use to respond to user requests (client side). Our data is stored in the MySql database, which we will connect to this database using PHP and respond to the client’s requests.

What is react?

ReactJS is not a programming language but a technology created using the JavaScript scripting language. In this tutorial, we will use React for user-side design. This technology increases the user experience and even increases the coding speed. React has made it simple for us how to send and receive data from the server and display it. This technology uses AJAX to send and receive data. If you are not familiar with AJAX, we have provided you with an article entitled How to use AJAX in WordPress, from which you can study the basic concepts of AJAX.

But for those who do not master ReactJS, we have also provided a PHP example of the comment system for these users, which we will discuss in our section.

What is ajax

Ajax (Asynchronous JavaScript and XML) is a set of web development techniques used to create interactive web applications. It is a combination of HTML, CSS, JavaScript, and the XMLHttpRequest object. Ajax allows for web pages to be updated asynchronously by exchanging small amounts of data with the server behind the scenes, without having to reload the entire page.

What is MySQL?

MySQL is a database where we can store our data. This database is one of the most powerful and popular databases that is used as a database in many websites today. WordPress, which is built with about 30% of the websites on the Internet today, also uses MySql as a database. If you are interested in how to work with a database in WordPress, we have provided an article with this title for you.

How to install PHP

You can use WampServer or Xampp software to install PHP on your local host. Both of these software simulates the site server on the local host and you can use it to launch PHP websites. This software installs Apache and MySQL at the same time, so there is no need to install them separately.

How to install ReactJS

We also use NodeJS to launch and install React. You can download and install this software from the official NodeJS site.

After installing NodeJS, it’s time to launch the project itself. We use VS Code editor software for the project. VS Code is open-source software that you can download and install from its official website.

MySQL database design for PHP and React comment system

First of all, we will design and implement the database. As we said, the comment system is a part of the website that we need different tables in the database to implement, but since our goal in this tutorial is only to implement the comment system, we will only implement the parts required for this system.

php react comment system

In the database, we need three tables in the following order.

  • Admin: It is a table where the information of website administrators is stored. We can even consider a table for users who have registered on our website. But because anyone (registered and unregistered users) can post comments on the website, so we avoid creating a table for registered users, but you can apply it in your project.
  • Post: Each comment belongs to a post or product, and we put the information of that post in the post table.
  • Comment: The comment table includes all user comments that are stored in this table.

Notes about the Comment table

  • Each post can have infinite comments, but each comment is specific to one post, so we store the post ID in this table.
  • Because we store both comments and replies in this table, we also store the details of the person who left the comment in this table. If the user is a member of the website administrators, his ID is stored in adminId, otherwise, user_email and user_name must be entered.
  • This comment system supports nested commenting, so we store the parent comment ID in parent_id. If there is no parent comment, 0 will be entered.

Now open phpMyAdmin and create a database named “comment_system”. Then enter the following queries to create the required tables that we have designed above so that the tables are created.

1. admin table

CREATE TABLE IF NOT EXISTS `admin` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` text NOT NULL,
  `username` text NOT NULL,
  `password` text NOT NULL,
  PRIMARY KEY (`id`)
)

2. comment table

CREATE TABLE IF NOT EXISTS `comment` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `comment` text NOT NULL,
  `user_email` text,
  `user_name` text,
  `date` datetime NOT NULL,
  `parent_id` int(11) NOT NULL,
  `status` tinyint(4) NOT NULL,
  `admin_id` int(11) DEFAULT NULL,
  `post_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
)

3. post table

CREATE TABLE IF NOT EXISTS `post` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` text NOT NULL,
  `content` text,
  `thumbnail` text,
  PRIMARY KEY (`id`)
)

How to create PHP and React comment system

After installing PHP and NodeJS, it’s time to create a React project.

The comment system uses React as the front end and PHP as the back end, so it is necessary to create a project where both ReactJS and PHP can be implemented. Because React can be executed in any folder on your system by NodeJS, so the limitation is on PHP. Go to the path you gave when installing Wamp or Xampp. If you are using Wamp, go to the “www” folder and if you are using Xampp, go to the “htdocs” folder.

Open VS Code in this folder and enter the following code in the terminal section.

npx create-react-app hs-comment-system

This command will start installing the React project. The term hs-comment-system is the name of the project, you can change it to your desired name.

After installing React, open the hs-comment-system folder using VS Code.

The React project contains a sample project that will run the sample designed page that we will modify later. Enter the following command in the Terminal to run the React project.

npm start

After running the project, you will see that NodeJS opens your browser and runs the project at the following address by default.

http://localhost:3000

Database class

In the root folder of the project, create a folder called classes and create database.php inside it and open it.

Enter the following codes in database.php.

<?php
class Database
{
    private $server_name = 'localhost';
    private $database_username = 'root';
    private $database_password = '';
    private $database_name = 'comment_system';
    private $connection = null;

    public function getPost($id)
    {
        $this->connection = new mysqli(
            $this->server_name,
            $this->database_username,
            $this->database_password,
            $this->database_name
        );
        $this->connection->set_charset('utf8');
        $sql = $this->connection->prepare(
            'SELECT * FROM `post` WHERE id=?'
        );
        $sql->bind_param('i', $id);
        $sql->execute();
        $result = $sql->get_result();
        if ($result->num_rows > 0) {
            $post = $result->fetch_assoc();
            $sql->close();
            $this->connection->close();
            return $post;
        }
        $sql->close();
        $this->connection->close();
        return false;
    }

    public function getComments($id)
    {
        $this->connection = new mysqli(
            $this->server_name,
            $this->database_username,
            $this->database_password,
            $this->database_name
        );
        $this->connection->set_charset('utf8');
        $sql = $this->connection->prepare(
            'SELECT 
            c.id id,
            c.comment `comment`,
            c.user_email email,
            c.user_name user_name,
            c.date `date`,
            c.parent_id parent_id,
            a.name admin_name
            FROM `comment` c 
            LEFT JOIN admin a 
            ON a.id = c.admin_id
            WHERE c.post_id=?
            ORDER BY date'
        );
        $sql->bind_param('i', $id);
        $sql->execute();
        $result = $sql->get_result();
        if ($result->num_rows > 0) {
            $comments = [];
            while ($row = $result->fetch_assoc()) {
                array_push($comments, $row);
            }
            $sql->close();
            $this->connection->close();
            return $comments;
        }
        $sql->close();
        $this->connection->close();
        return false;
    }

    public function insertComment($comment)
    {
        $this->connection = new mysqli(
            $this->server_name,
            $this->database_username,
            $this->database_password,
            $this->database_name
        );
        $this->connection->set_charset('utf8');
        $sql = $this->connection->prepare(
            'INSERT INTO `comment`(`comment`, `user_email`, `user_name`, `date`, `parent_id`, `status`, `admin_id`, `post_id`) VALUES (?,?,?,?,?,?,?,?)'
        );
        $sql->bind_param(
            'ssssiiii',
            $comment['comment'],
            $comment['user_email'],
            $comment['user_name'],
            $comment['date'],
            $comment['parent_id'],
            $comment['status'],
            $comment['admin_id'],
            $comment['post_id']
        );
        if ($sql->execute()) {
            $sql->close();
            $this->connection->close();
            return true;
        }

        $error = $this->connection->errno;
        $sql->close();
        $this->connection->close();
        return $error;
    }
}

This file contains the database class, which is responsible for connecting to the database. This class also has three functions which are as follows.

This project is implemented in the form of three-layer programming, where the database.php file is actually the data layer.

  • getPost: get post information from the database.
  • getComments: get post comments from the database.
  • inserComment: Save the comment in the MySQL database

API file

This system works as a REST API, so all requests are sent to the api.php file. In the root folder of the project, create a file called api.php and save the following codes in it.

<?php
include './classes/database.php';

$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$uri = explode('/', $uri);

$action = $uri[3];

$database = new Database();

if ($action === 'post') {
    $post_id = $uri[4];

    if ($post = $database->getPost($post_id)) {
        return_json(['post' => $post]);
    }
} elseif ($action === 'addcomment') {
    $rest_json = file_get_contents('php://input');
    $_POST = json_decode($rest_json, true);
    $post_id = $_POST['postId'];
    $comment = $_POST['comment'];
    $name = $_POST['name'];
    $email = $_POST['email'];
    $parentId = $_POST['parentId'];

    if (
        $database->insertComment([
            'comment' => $comment,
            'user_email' => $email,
            'user_name' => $name,
            'date' => date('Y-m-d H:i:s'),
            'parent_id' => $parentId,
            'status' => 0,
            'admin_id' => null,
            'post_id' => $post_id,
        ])
    ) {
        return_json(['comments' => $database->getComments($post_id)]);
    }
} 
elseif ($action === 'comments') {
    $post_id = $uri[4];
    return_json(['comments' => $database->getComments($post_id)]);
}

return_json(['status' => 0]);

function return_json($arr)
{
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Headers: *');
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($arr);
    exit();
}

All requests are sent to this file, which is as follows.

In three-layer programming, this api.php file is actually the business layer.

  • post: It is used to receive post information.
  • addcomment: It is used to enter a comment in the database.
  • comments: Returns all post comments.
  • return_json function: displays the information received from the database as JSON for the user.

In the database design, in the comment table, we have a field called admin_id, which is entered when the commenter is one of the website admins. There are different methods to get the ID of this admin, which is known as the login system. We have prepared an article on this website called How To Create Login Form with PHP and React for you.

Install React requirement components

In order to use React for this project, we need to install the components that need to be installed by entering the following commands in the terminal.

npm install react-dom
npm install react-router-dom

File index.js

By default, all React projects start executing codes from the index.js file. Open the index.js file and put the following codes in it.

import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.css'
import App from './App'
import reportWebVitals from './reportWebVitals'
import { BrowserRouter, Route, Routes } from 'react-router-dom'

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  <React.StrictMode>
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<App />} />
      </Routes>
    </BrowserRouter>
  </React.StrictMode>,
)

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals()

App.js file

Like the index.js file, React projects also have App.js file by default. Open this file and put the following codes in it.

import './App.css'
import { useCallback, useEffect, useState } from 'react'

function App() {
  const [post, setPost] = useState()
  const [comments, setComments] = useState()
  const [name, setName] = useState('')
  const [email, setEmail] = useState('')
  const [parentId, setParentId] = useState({ id: 0, name: '' })
  const [comment, setComment] = useState('')

  const getPost = useCallback(async () => {
    try {
      await fetch('http://localhost/hs-comment-system/api/post/1')
        .then((respose) => {
          if (respose.ok) {
            return respose.json()
          }
          throw new Error('error')
        })
        .then(async (data) => {
          setPost(data.post)
          await fetch(
            `http://localhost/hs-comment-system/api/comments/${data.post.id}`,
          )
            .then((respose) => {
              if (respose.ok) {
                return respose.json()
              }
              throw new Error('error')
            })
            .then((data) => {
              if (data.comments) {
                setComments(data.comments)
              } else {
                //set error
              }
            })
        })
    } catch (error) {
      console.log(error.message)
    }
  }, [])

  useEffect(() => {
    getPost()
  }, [getPost])

  const submitHandler = async (event) => {
    event.preventDefault()
    try {
      await fetch('http://localhost/hs-comment-system/api/addcomment', {
        method: 'POST',
        body: JSON.stringify({
          postId: 1,
          comment: comment,
          name: name,
          email: email,
          parentId: parentId.id,
        }),
      })
        .then((respose) => {
          if (respose.ok) {
            return respose.json()
          }
          throw new Error('error')
        })
        .then((data) => {
          if (data.comments) {
            setComments(data.comments)
            setParentId({ id: 0, name: '' })
            setName('')
            setEmail('')
            setComment('')
          } else {
            //set error
          }
        })
    } catch (error) {
      console.log(error.message)
    }
  }
  const arrangeComments = (parent_id) => {
    return (
      <>
        {comments.map((comment) => {
          return (
            comment.parent_id === parent_id && (
              <>
                <div
                  className="comment"
                  style={{
                    border: '1px solid #333333',
                    padding: '10px',
                    borderRadius: '5px',
                    marginBottom: '10px',
                  }}
                >
                  <div style={{ display: 'flex', alignItems: 'center' }}>
                    <div style={{ width: '50%' }}>
                      {comment.user_name
                        ? comment.user_name
                        : comment.admin_name}
                    </div>
                    <div
                      style={{
                        width: '50%',
                        display: 'flex',
                        justifyContent: 'end',
                      }}
                    >
                      {comment.date}
                      <span
                        style={{
                          marginLeft: '15px',
                          border: '1px solid #333',
                          display: 'inline-block',
                          padding: '5px',
                          cursor: 'pointer',
                        }}
                        onClick={() => {
                          setParentId({
                            id: comment.id,
                            name: comment.user_name
                              ? comment.user_name
                              : comment.admin_name,
                          })
                        }}
                      >
                        Reply
                      </span>
                    </div>
                  </div>
                  <div>{comment.comment}</div>
                </div>
                <div className="sub-comment" style={{ marginLeft: '30px' }}>
                  {has_children(comment.id) === true &&
                    arrangeComments(comment.id)}
                </div>
              </>
            )
          )
        })}
      </>
    )
  }

  function has_children(id) {
    let result = false
    comments.forEach((comment) => {
      if (comment.parent_id === id) {
        result = true
      }
    })
    return result
  }

  return (
    <div className="App" style={{marginTop:'15px',marginBottom:'15px'}}>
      {post && (
        <div
          style={{
            maxWidth: '1170px',
            marginLeft: 'auto',
            marginRight: 'auto',
          }}
        >
          <article>
            <div>
              {post.thumbnail && (
                <img
                  src={post.thumbnail}
                  alt={post.title}
                  style={{ maxWidth: '600px' }}
                />
              )}
            </div>
            <h1>{post.title}</h1>
            <p>{post.content}</p>
          </article>
          <section>
            <div>{comments && <>{arrangeComments(0)}</>}</div>
            <form
              className="comment-form"
              onSubmit={submitHandler}
              style={{ border: '1px solid #333', padding: '10px',maxWidth:'50%' }}
            >
              {parentId.id > 0 && (
                <div>
                  Reply to: {parentId.name}
                  <span
                    style={{
                      marginLeft: '30px',
                      border: '1px solid #333',
                      padding: '3px',
                      cursor:'pointer',
                      borderRadius:'2px'
                    }}
                    onClick={() => {
                      setParentId({ id: 0, name: '' })
                    }}
                  >
                    X
                  </span>
                </div>
              )}
              <div style={{ display: 'flex', marginTop: '15px' }}>
                <div style={{ width: '50%' }}>
                  <label style={{ width: '100%' }}>Name</label>
                  <input
                    style={{ width: '100%', padding: '5px' }}
                    type="text"
                    value={name}
                    onChange={(event) => {
                      setName(event.target.value)
                    }}
                  />
                </div>
                <div style={{ width: '50%' }}>
                  <label style={{ width: '100%' }}>Email</label>
                  <input
                    style={{ width: '100%', padding: '5px' }}
                    type="text"
                    value={email}
                    onChange={(event) => {
                      setEmail(event.target.value)
                    }}
                  />
                </div>
              </div>
              <div style={{ marginTop: '15px' }}>
                <label style={{ width: '100%' }}>Comment</label>
                <textarea
                  style={{ width: '100%', padding: '5px' }}
                  value={comment}
                  onChange={(event) => {
                    setComment(event.target.value)
                  }}
                />
              </div>
              <div>
                <input
                  type="submit"
                  value="Send"
                  style={{
                    padding: '15px',
                    background: '#333',
                    color: '#fff',
                    border: 'none',
                    marginTop: '15px',
                  }}
                />
              </div>
            </form>
          </section>
        </div>
      )}
    </div>
  )
}

export default App

This file is responsible for displaying data and sending and receiving information to the server.

The getPost function sends a request to the “API” address. Because this code is a sample code, at the end of the address, the ID of the post is entered statically (number 1), which in real projects, this number will be dynamically placed in the address.

const getPost = useCallback(async () => {
    try {
      await fetch('http://localhost/hs-comment-system/api/post/1')
        .then((respose) => {
          if (respose.ok) {
            return respose.json()
          }
          throw new Error('error')
        })
        .then(async (data) => {
          setPost(data.post)
          await fetch(
            `http://localhost/hs-comment-system/api/comments/${data.post.id}`,
          )
            .then((respose) => {
              if (respose.ok) {
                return respose.json()
              }
              throw new Error('error')
            })
            .then((data) => {
              if (data.comments) {
                setComments(data.comments)
              } else {
                //set error
              }
            })
        })
    } catch (error) {
      console.log(error.message)
    }
  }, [])

  useEffect(() => {
    getPost()
  }, [getPost])

After receiving the post information, this code will receive the comments if the correct information has been sent and received. In real projects, only one request is sent to the server and all the post information and comments are returned to reduce the server load.

In this code, the useEffect hook is executed once when entering the page and calls the getPost function.

const submitHandler = async (event) => {
    event.preventDefault()
    try {
      await fetch('http://localhost/hs-comment-system/api/addcomment', {
        method: 'POST',
        body: JSON.stringify({
          postId: 1,
          comment: comment,
          name: name,
          email: email,
          parentId: parentId.id,
        }),
      })
        .then((respose) => {
          if (respose.ok) {
            return respose.json()
          }
          throw new Error('error')
        })
        .then((data) => {
          if (data.comments) {
            setComments(data.comments)
            setParentId({ id: 0, name: '' })
            setName('')
            setEmail('')
            setComment('')
          } else {
            //set error
          }
        })
    } catch (error) {
      console.log(error.message)
    }
  }

The submitHandler function also sends the comment form information to the server to be stored in the database. If sending and saving are done correctly, all the comments of that post plus the new comment will be returned from the server side to be displayed in the list.

php react comment system

As we said, the comment system displays nested comments in this project. There are two ways to do this, one is to sort it in the database using SQL commands and the other is to use React on the user side. We do this nested sorting on the user side in the comment system using PHP and React. To reduce the server load.

const arrangeComments = (parent_id) => {
    return (
      <>
        {comments.map((comment) => {
          return (
            comment.parent_id === parent_id && (
              <>
                <div
                  className="comment"
                  style={{
                    border: '1px solid #333333',
                    padding: '10px',
                    borderRadius: '5px',
                    marginBottom: '10px',
                  }}
                >
                  <div style={{ display: 'flex', alignItems: 'center' }}>
                    <div style={{ width: '50%' }}>
                      {comment.user_name
                        ? comment.user_name
                        : comment.admin_name}
                    </div>
                    <div
                      style={{
                        width: '50%',
                        display: 'flex',
                        justifyContent: 'end',
                      }}
                    >
                      {comment.date}
                      <span
                        style={{
                          marginLeft: '15px',
                          border: '1px solid #333',
                          display: 'inline-block',
                          padding: '5px',
                          cursor: 'pointer',
                        }}
                        onClick={() => {
                          setParentId({
                            id: comment.id,
                            name: comment.user_name
                              ? comment.user_name
                              : comment.admin_name,
                          })
                        }}
                      >
                        Reply
                      </span>
                    </div>
                  </div>
                  <div>{comment.comment}</div>
                </div>
                <div className="sub-comment" style={{ marginLeft: '30px' }}>
                  {has_children(comment.id) === true &&
                    arrangeComments(comment.id)}
                </div>
              </>
            )
          )
        })}
      </>
    )
  }

  function has_children(id) {
    let result = false
    comments.forEach((comment) => {
      if (comment.parent_id === id) {
        result = true
      }
    })
    return result
  }

The above two functions are responsible for sorting and displaying nested comments. The list of comments is stored in the comments variable after receiving it from the server, and we use these two functions to display its comments nested.

return (
    <div className="App" style={{marginTop:'15px',marginBottom:'15px'}}>
      {post && (
        <div
          style={{
            maxWidth: '1170px',
            marginLeft: 'auto',
            marginRight: 'auto',
          }}
        >
          <article>
            <div>
              {post.thumbnail && (
                <img
                  src={post.thumbnail}
                  alt={post.title}
                  style={{ maxWidth: '600px' }}
                />
              )}
            </div>
            <h1>{post.title}</h1>
            <p>{post.content}</p>
          </article>
          <section>
            <div>{comments && <>{arrangeComments(0)}</>}</div>
            <form
              className="comment-form"
              onSubmit={submitHandler}
              style={{ border: '1px solid #333', padding: '10px',maxWidth:'50%' }}
            >
              {parentId.id > 0 && (
                <div>
                  Reply to: {parentId.name}
                  <span
                    style={{
                      marginLeft: '30px',
                      border: '1px solid #333',
                      padding: '3px',
                      cursor:'pointer',
                      borderRadius:'2px'
                    }}
                    onClick={() => {
                      setParentId({ id: 0, name: '' })
                    }}
                  >
                    X
                  </span>
                </div>
              )}
              <div style={{ display: 'flex', marginTop: '15px' }}>
                <div style={{ width: '50%' }}>
                  <label style={{ width: '100%' }}>Name</label>
                  <input
                    style={{ width: '100%', padding: '5px' }}
                    type="text"
                    value={name}
                    onChange={(event) => {
                      setName(event.target.value)
                    }}
                  />
                </div>
                <div style={{ width: '50%' }}>
                  <label style={{ width: '100%' }}>Email</label>
                  <input
                    style={{ width: '100%', padding: '5px' }}
                    type="text"
                    value={email}
                    onChange={(event) => {
                      setEmail(event.target.value)
                    }}
                  />
                </div>
              </div>
              <div style={{ marginTop: '15px' }}>
                <label style={{ width: '100%' }}>Comment</label>
                <textarea
                  style={{ width: '100%', padding: '5px' }}
                  value={comment}
                  onChange={(event) => {
                    setComment(event.target.value)
                  }}
                />
              </div>
              <div>
                <input
                  type="submit"
                  value="Send"
                  style={{
                    padding: '15px',
                    background: '#333',
                    color: '#fff',
                    border: 'none',
                    marginTop: '15px',
                  }}
                />
              </div>
            </form>
          </section>
        </div>
      )}
    </div>
  )

In this section, we display the post information after receiving it and then call the arrangeComments function to display the comments.

Display nested comment system in PHP

This section is for those developers that they don’t use React as the front end. In this section, we will display nested comments with just PHP.

<?php
$post_id = 1;

$url = 'http://localhost/hs-comment-system/api/comments/' . $post_id;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 4);
$comments = curl_exec($ch);
if (!$comments) {
    echo curl_error($ch);
} else {
    curl_close($ch);
    $json_result = json_decode($comments);

    echo arrange_comments($json_result->comments);
}

function arrange_comments($comments, $parent = 0)
{
    $result = '<ul>';
    foreach ($comments as $comment) {
        if ($comment->parent_id == $parent) {
            $result .= "<li>{$comment->comment}";

            if (has_children($comments, $comment->id)) {
                $result .= arrange_comments($comments, $comment->id);
            }
            $result .= '</li>';
        }
    }
    $result .= '</ul>';
    return $result;
}

function has_children($comments, $id)
{
    foreach ($comments as $comment) {
        if ($comment->parent_id == $id) {
            return true;
        }
    }
    return false;
}

The first section (curl) gets comments from the API and passes the received data to the arrange_comments function.

The arrange_comments function displayed comments in the nested list (ul tag).

The has_childeren function checks if the comment has children or not.

PHP and React comment system conclusion

In this article you learned how to make a comment system for your website with PHP as the backend and front end, React as the front end, MySQL as the database with AJAX technology, and a reply mechanism to comments.

You can download the project from GitHub.

After downloading the project, open the folder with VS Code and run the below code in the terminal.

npm install

This code will install the required files for PHP and React comment system. After installation, run the below code to start the project.

npm start
Shopping Cart