HTML CSS JavaScript jQuery PHP Python MySQL

Review System with PHP, MySQL, and AJAX

Posted on by David Adams

Review System with PHP, MySQL, and AJAX

In this tutorial we'll be creating a review system with PHP, MySQL, and AJAX (JavaScript).

We'll be able to add the review system to any webpage, even an HTML document, how is this possible? We're going to use AJAX to fetch results from our PHP server, this will be determined by the webpage the user is currently on.

You'll be able to implement this review system into your website hassle-free, as long as you have PHP and MySQL installed.

The Basic and Advanced packages include additional features and a download link to the source code.

1. Getting Started

If you want to try the review system on your local webserver you'll need to install a webserver environment, follow the below instructions.

  • Install a webserver environment, I recommend XAMPP.
  • If you have your own webserver (VPS, Dedicated, etc) you'll need to install PHP, Apache, MySQL, and phpMyAdmin (Note: these are already included with XAMPP).
  • Install a code editor, you can use Notepad but I don't recommend it, use one of the following: Notepad++, Visual Studio Code, or Atom.

2. Creating the Database and setting-up Tables

Now we need to create the MySQL database and create the reviews table, we can do this with phpMyAdmin.

Navigate to phpMyAdmin (e.g. http://localhost/phpmyadmin/) in your browser and follow the below instructions:

  • Click the Databases tab at the top
  • Under Create database, type in phpreviews in the text box
  • Select utf8_general_ci as the collation (UTF-8 is the default encoding in HTML5)
  • Click Create

While the database is selected click the SQL tab and execute the following statement:

SQL Copy
CREATE TABLE IF NOT EXISTS `reviews` (
	`id` int(11) NOT NULL AUTO_INCREMENT,
	`page_id` int(11) NOT NULL,
	`name` varchar(255) NOT NULL,
	`content` text NOT NULL,
	`rating` tinyint(1) NOT NULL,
	`submit_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
	PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;

INSERT INTO `reviews` (`id`, `page_id`, `name`, `content`, `rating`, `submit_date`) VALUES
(1, 1, 'David Deacon', 'I use this website daily, the amount of content is brilliant.', 5, '2020-01-09 20:43:02'),
(2, 1, 'John Doe', 'Great website, great content, and great support!', 4, '2020-01-09 21:00:41'),
(3, 1, 'Robert Billings', 'Website needs more content, good website but content is lacking.', 3, '2020-01-09 21:10:16'),
(4, 1, 'Daniel Callaghan', 'Great!', 5, '2020-01-09 23:51:05'),
(5, 1, 'Bobby', 'Not much content.', 2, '2020-01-14 21:54:24'),
(6, 1, 'Joshua Kennedy', 'Fantasic website, has everything I need to know.', 5, '2020-01-16 17:34:27'),
(7, 1, 'Johannes Hansen', 'Really like this website, helps me out a lot!', 5, '2020-01-16 17:35:12'),
(8, 1, 'Wit Kwiatkowski', 'Please provide more quality content.', 5, '2020-01-16 17:36:03'),
(9, 1, 'Óli Þórðarson', 'Thanks', 5, '2020-01-16 17:36:34'),
(10, 1, 'Jaroslava Beránková', '', 5, '2020-01-16 17:37:48'),
(11, 1, 'Naomi Holt', 'Appreciate the amount of content you guys do.', 5, '2020-01-16 17:39:17'),
(12, 1, 'Isobel Whitehead', 'Thank you for providing a website that helps us out a lot!', 5, '2020-01-16 17:40:28'),
(13, 1, 'Warren Mills', 'Everything is awesome!', 5, '2020-01-16 19:34:08'),
(14, 1, 'Larry Johnson', 'Brilliant, thank you for providing quality content!', 5, '2020-01-29 18:40:36');

The data that we insert into the reviews table will be for testing purposes.

This will create the reviews table with the following columns:

  • id — The unique review ID.
  • page_id — This will determine which review is for which page, it will be the page ID that you can specify on any webpage.
  • name — The name of the user (e.g. Joe Bloggs).
  • content — The review content, this will be what the user inputs.
  • rating — The review rating that will be from 1 to 5.
  • submit_date — The date the review was posted.

On phpMyAdmin this should look like:

http://localhost/phpmyadmin/
MySQL Reviews Table

3. Creating the Stylesheets (CSS3)

We'll be creating 2 stylesheets for our review system, one will be for our home page, this page will be used as an example of how we'll implement the review system, and the other stylesheet will be used for the review system.

Stylesheets are used to format the layout of our review system.

Create the style.css file and add:

CSS Copy
* {
    box-sizing: border-box;
    font-family: -apple-system, BlinkMacSystemFont, "segoe ui", roboto, oxygen, ubuntu, cantarell, "fira sans", "droid sans", "helvetica neue", Arial, sans-serif;
    font-size: 16px;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
body {
    background-color: #FFFFFF;
    margin: 0;
}
.navtop {
    background-color: #3f69a8;
    height: 60px;
    width: 100%;
    border: 0;
}
.navtop div {
    display: flex;
    margin: 0 auto;
    width: 1000px;
    height: 100%;
}
.navtop div h1, .navtop div a {
    display: inline-flex;
    align-items: center;
}
.navtop div h1 {
    flex: 1;
    font-size: 24px;
    padding: 0;
    margin: 0;
    color: #ecf0f6;
    font-weight: normal;
}
.navtop div a {
    padding: 0 20px;
    text-decoration: none;
    color: #c5d2e5;
    font-weight: bold;
}
.navtop div a i {
    padding: 2px 8px 0 0;
}
.navtop div a:hover {
    color: #ecf0f6;
}
.content {
    width: 1000px;
    margin: 0 auto;
}
.content h2 {
    margin: 0;
    padding: 25px 0;
    font-size: 22px;
    border-bottom: 1px solid #ebebeb;
    color: #666666;
}

Create the reviews.css file and add:

CSS Copy
.reviews .overall_rating .num {
    font-size: 30px;
    font-weight: bold;
    color: #F5A624;
}
.reviews .overall_rating .stars {
    letter-spacing: 3px;
    font-size: 32px;
    color: #F5A624;
    padding: 0 5px 0 10px;
}
.reviews .overall_rating .total {
    color: #777777;
    font-size: 14px;
}
.reviews .write_review_btn, .reviews .write_review button {
    display: inline-block;
    background-color: #565656;
    color: #fff;
    text-decoration: none;
    margin: 10px 0 0 0;
    padding: 5px 10px;
    border-radius: 5px;
    font-size: 14px;
    font-weight: 600;
    border: 0;
}
.reviews .write_review_btn:hover, .reviews .write_review button:hover {
    background-color: #636363;
}
.reviews .write_review {
    display: none;
    padding: 20px 0 10px 0;
}
.reviews .write_review textarea {
    width: 100%;
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 5px;
    height: 150px;
    margin-top: 10px;
}
.reviews .write_review input {
    display: block;
    width: 250px;
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 5px;
    margin-top: 10px;
}
.reviews .write_review button {
    cursor: pointer;
}
.reviews .review {
    padding: 20px 0;
    border-bottom: 1px solid #eee;
}
.reviews .review .name {
    padding: 0 0 3px 0;
    margin: 0;
    font-size: 18px;
    color: #555555;
}
.reviews .review .rating {
    letter-spacing: 2px;
    font-size: 22px;
    color: #F5A624;
}
.reviews .review .date {
    color: #777777;
    font-size: 14px;
}
.reviews .review .content {
    padding: 5px 0;
}
.reviews .review:last-child {
    border-bottom: 0;
}

4. Creating the Review System with PHP

We can now start coding our review system with PHP, the script we're going to create will select results from our database and output the reviews in HTML format.

Create the reviews.php file and add:

PHP Copy
<?php
// Update the details below with your MySQL details
$DATABASE_HOST = 'localhost';
$DATABASE_USER = 'root';
$DATABASE_PASS = '';
$DATABASE_NAME = 'phpreviews';
try {
    $pdo = new PDO('mysql:host=' . $DATABASE_HOST . ';dbname=' . $DATABASE_NAME . ';charset=utf8', $DATABASE_USER, $DATABASE_PASS);
} catch (PDOException $exception) {
    // If there is an error with the connection, stop the script and display the error.
    exit('Failed to connect to database!');
}

The code above will connect to our MySQL database (phpreviews), make sure to update the MySQL database connection variables.

Add after:

PHP Copy
// Below function will convert datetime to time elapsed string.
function time_elapsed_string($datetime, $full = false) {
    $now = new DateTime;
    $ago = new DateTime($datetime);
    $diff = $now->diff($ago);
    $diff->w = floor($diff->d / 7);
    $diff->d -= $diff->w * 7;
    $string = array('y' => 'year', 'm' => 'month', 'w' => 'week', 'd' => 'day', 'h' => 'hour', 'i' => 'minute', 's' => 'second');
    foreach ($string as $k => &$v) {
        if ($diff->$k) {
            $v = $diff->$k . ' ' . $v . ($diff->$k > 1 ? 's' : '');
        } else {
            unset($string[$k]);
        }
    }
    if (!$full) $string = array_slice($string, 0, 1);
    return $string ? implode(', ', $string) . ' ago' : 'just now';
}

This function will be used to format the review date, for example, this date "2020-01-09 20:43:02" will be formatted to "3 weeks ago".

Add after:

PHP Copy
// Page ID needs to exist, this is used to determine which reviews are for which page.
if (isset($_GET['page_id'])) {
    if (isset($_POST['name'], $_POST['rating'], $_POST['content'])) {
        // Insert a new review (user submitted form)
        $stmt = $pdo->prepare('INSERT INTO reviews (page_id, name, content, rating, submit_date) VALUES (?,?,?,?,NOW())');
        $stmt->execute([$_GET['page_id'], $_POST['name'], $_POST['content'], $_POST['rating']]);
        exit('Your review has been submitted!');
    }
    // Get all reviews by the Page ID ordered by the submit date
    $stmt = $pdo->prepare('SELECT * FROM reviews WHERE page_id = ? ORDER BY submit_date DESC');
    $stmt->execute([$_GET['page_id']]);
    $reviews = $stmt->fetchAll(PDO::FETCH_ASSOC);
    // Get the overall rating and total amount of reviews
    $stmt = $pdo->prepare('SELECT AVG(rating) AS overall_rating, COUNT(*) AS total_reviews FROM reviews WHERE page_id = ?');
    $stmt->execute([$_GET['page_id']]);
    $reviews_info = $stmt->fetch(PDO::FETCH_ASSOC);
} else {
    exit('Please provide the page ID.');
}
?>

With the above code we use a GET request that will get the page ID (e.g. reviews.php?page_id=1), and with that page ID we get all the results from our database ordered by the review submit date (newest first).

But not only do we need the reviews from our database we also need to calculate the rating, to do that we can execute a separate query that will calculate the average rating (using the MySQL AVG() function) and get the total number of reviews (using the MySQL COUNT() function).

Also take note prepared statements will prevent SQL injection, so you don't need to worry about security.

After this line:

if (isset($_GET['page_id'])) {

Add:

PHP Copy
if (isset($_POST['name'], $_POST['rating'], $_POST['content'])) {
    // Insert a new review (user submitted form)
    $stmt = $pdo->prepare('INSERT INTO reviews (page_id, name, content, rating, submit_date) VALUES (?,?,?,?,NOW())');
    $stmt->execute([$_GET['page_id'], $_POST['name'], $_POST['content'], $_POST['rating']]);
    exit('Your review has been submitted!');
}

What this will do is insert a new review into our reviews table in our database, but only if the user has submitted the "write review" form, this form will contain fields for name, rating, and content.

At the very end of the file add (just after the PHP closing tag):

PHP Copy
<div class="overall_rating">
    <span class="num"><?=number_format($reviews_info['overall_rating'], 1)?></span>
    <span class="stars"><?=str_repeat('&#9733;', round($reviews_info['overall_rating']))?></span>
    <span class="total"><?=$reviews_info['total_reviews']?> reviews</span>
</div>
<a href="#" class="write_review_btn">Write Review</a>
<div class="write_review">
    <form>
        <input name="name" type="text" placeholder="Your Name" required>
        <input name="rating" type="number" min="1" max="5" placeholder="Rating (1-5)" required>
        <textarea name="content" placeholder="Write your review here..." required></textarea>
        <button type="submit">Submit Review</button>
    </form>
</div>
<?php foreach ($reviews as $review): ?>
<div class="review">
    <h3 class="name"><?=htmlspecialchars($review['name'], ENT_QUOTES)?></h3>
    <div>
        <span class="rating"><?=str_repeat('&#9733;', $review['rating'])?></span>
        <span class="date"><?=time_elapsed_string($review['submit_date'])?></span>
    </div>
    <p class="content"><?=htmlspecialchars($review['content'], ENT_QUOTES)?></p>
</div>
<?php endforeach ?>

This is the template for our review system, with the above code all the reviews will be iterated and displayed vertically.

The average rating and the total number of reviews will be displayed at the top, the rating is from 1 to 5 stars.

This is everything you need to do on the back-end, next we'll be using AJAX to get the results and then display them.

5. Implementing the Review System into our Webpage with AJAX

Now that we have created the back-end code we can create the front-end code, remember that we can add this to any webpage, the webpage used below is just an example of how you implement the review system.

Create the index.html file and add:

HTML Copy
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>Reviews System</title>
		<link href="style.css" rel="stylesheet" type="text/css">
		<link href="reviews.css" rel="stylesheet" type="text/css">
	</head>
	<body>
	    <nav class="navtop">
	    	<div>
	    		<h1>Reviews System</h1>
	    	</div>
	    </nav>
		<div class="content home">
			<h2>Reviews</h2>
			<p>Check out the below reviews for our website.</p>
		</div>
	</body>
</html>

This is the webpage we'll be using to test out the review system

After this line:

<p>Check out the below reviews for our website.</p>

Add:

HTML Copy
<div class="reviews"></div>
<script>
const reviews_page_id = 1;
fetch("reviews.php?page_id=" + reviews_page_id).then(response => response.text()).then(data => {
	document.querySelector(".reviews").innerHTML = data;
	document.querySelector(".reviews .write_review_btn").onclick = event => {
		event.preventDefault();
		document.querySelector(".reviews .write_review").style.display = 'block';
		document.querySelector(".reviews .write_review input[name='name']").focus();
	};
	document.querySelector(".reviews .write_review form").onsubmit = event => {
		event.preventDefault();
		fetch("reviews.php?page_id=" + reviews_page_id, {
			method: 'POST',
			body: new FormData(document.querySelector(".reviews .write_review form"))
		}).then(response => response.text()).then(data => {
			document.querySelector(".reviews .write_review").innerHTML = data;
		});
	};
});
</script>

And now if we navigate to http://localhost/phpreviews/index.html it will look something like this:

http://localhost/phpreviews/index.html
PHP and AJAX Review System

If we want to change the page ID we can update the reviews_page_id variable, you can add the above code to any webpage, the only code you need to update is the reviews_page_id variable, every page should have a unique page ID.

You can put the AJAX code in a separate JavaScript file if you want to, just remember the reviews_page_id variable needs to be specified.

That's everything you need to do to create a review system with PHP, MySQL and AJAX.

Conclusion

Congratulations! You've successfully created a review system with PHP, MySQL, and AJAX!

If you've enjoyed this article consider sharing it with the social links below and/or drop a comment, I enjoy creating quality content that will help you guys!

Enjoy coding!

If you would like to support us consider purchasing a package below, this will greatly help us create more tutorials and keep our server up and running, packages include improved code and more features.

Basic

Advanced

Source code
Database SQL file
Secure Review System
Sort by feature
Pagination feature
Upload images/photos feature
1 review per user feature
AJAX Indicator (circle loader) feature
JavaScript Class
AJAX integration
SCSS file
Commented code
Free updates
Free support (bugs and minor issues)
User Guide
* Payments are processed with PayPal.
* Advanced package also includes the basic package.
* Both packages include tutorial source.

$5.00

Download

$10.00

Download