Meta Box Lite
Meta Box

How to Create the Rating Feature for a WordPress Website - Using MB Views

Rating is an essential feature for any product, since customer reviews are objective and can help make your product more trustworthy. You can create it along with some advanced functionalities with the help of MB Views. Let’s explore it.

For demonstration, I will add the rating feature for the restaurant list.

Demonstration of creating the rating feature for restaurants

Specifically, this feature includes a frontend review form that allows the customer to rate and provide feedback. Then, we’ll have an archive page that shows all the restaurants along with the average rating from guests.

Video Version

Before Getting Started

In the case that you want to create the rating feature for a restaurant, product, or something, you’ll need to create a custom post type for it. Then, add a custom field for extra information.

Besides that, we need the advanced features from Meta Box extensions. So, instead of installing them separately, we highly recommend you use Meta Box AIO to have a framework and all the advanced features from the extensions, including:

  • MB Admin Columns: to show a post type or a field as a column in the admin screen.
  • MB Custom Post Types: to create a custom post type for the restaurants and reviews.
  • MB Frontend Submission: to create forms for users to submit their reviews from the frontend.
  • MB Views: to create templates for displaying rating on the page.
  • MB Builder: to have UI in the backend to create custom fields and forms visually.

I will focus on the two main goals as I said at first. So, I skipped some basic steps, such as creating custom post types, custom fields, and templates for displaying data from the field,s to save time. If you don’t know how to create them yet, you should check out our previous tutorials on this channel or blog page.

Now, let’s go.

Create the Rating Form

I’ve already created two custom post types: restaurant and rating, and two field groups as well.

The created custom post types and field groups

For the field group applied to the restaurant post type, I add some fields to add extra information for the restaurants.

The field in the field group of the restaurant.

It displays on the frontend as below:

The basic information is displayed on the frontend

The remaining field group is for the frontend form, including fields that you want to display on the rating form so that the customers can fill in their feedback and information. You can change the field types and their settings.

The field in the field group of review form

We’ll add the review form on this page after the content. I also use the template for displaying restaurant information, then add some code.

<div class="review-button">
    <i class="fa-solid fa-pen-to-square"></i> Write a review
</div>
[mb_frontend_form id='review-information' post_fields='title' label_title='Name']

Add code for adding the form to the page on the frontend

In there:

  • <i class="fa-solid fa-pen-to-square"></i> Write a review: is to add a line to the page with the specified content. You can change it as you want
  • [mb_frontend_form id='review-information' post_fields='title' label_title='Name']: is the generated shortcode when you publish the field group of the form. Then, I edit it a little bit to have a meta box as the post title additionally with its label is Name.

Now, let’s see a restaurant on the frontend. Our form is shown with all the fields I want.

The review form is shown

However, pay attention to the last field. Normally, you can choose the post from the list. But that seems a bit clunky and time-consuming. I’ll get it automatically using JavaScript.

Back to the template, add a line of code to declare that we’ll use the JavaScript library.

Add code for declaring using JavaScript

Then, move to the JavaScript tab to add some code.

jQuery( function( $ ) {
    var bodyClass = $( 'body' ).attr( 'class' );
    var match = bodyClass.match( /postid-(\d+)/ );
    if (match && match[1]) {
        var restaurantId = match[1];
        var $select = $(' select[name="restaurant"]' );
        if ( $select.length ) {
            $select.val( restaurantId).trigger('change' );
        }
    }
});

Add JavaScript

Specifically:

  • var bodyClass = $( 'body' ).attr( 'class' ): is to get the ID from the body classes.
  • var match = bodyClass.match( /postid-(\d+)/ ): is to save the current post.
  • The remaining code is to automatically choose the value of the restaurant that is the same as the ID from the drop-down list.

After updating the template, the post displayed as the default choice without selecting it on the form.

The restaurant is selected automatically

You can try entering a review. And it will be saved as a post of the review post type with the post title as the name.

We’ve finished the review form. However, I’d like to show the submitted entries on this page so that all customers can see them. So, I’ll add one more small step.

Display Submitted Reviews of the Current Post

Go back to our template and add some code.

{% set restaurant_id = post.ID %}
{% set posts = mb.get_posts({
    post_type: 'review',
    posts_per_page: -1,
    meta_query: [
        {
            key: 'restaurant',
            value: restaurant_id,
            compare: '='
        }
    ],
    orderby: 'date',
    order: 'DESC'
}) %}

Loop through all the review posts

Explanation:

  • {% set restaurant_id = post.ID %}: is to get the ID of the current restaurant.
  • mb.get_posts({}): is the Meta Box function to get posts. In this case, we loop through all the posts of the review post type. Then, choose the post that has a value of the restaurant field that matches the restaurant ID.

For each selected review, we’ll show details information including avatar, name, review day, rating, and feedback. Simply use the Insert Field button to select the field you want to display. For instance, click on this one to insert the field of avatar, then choose the image size. I also add some div tags and classes for easier styling. Do the same for the name and date.

Insert fields to get data from them

For the rating, I use the part below to transform the value of the range field to stars.

{% set rating = post.rating|default(0) %}
{% for i in 1..5 %}
    {% if rating >= i %}
        <i class="fas fa-star"></i>
{% elseif rating >= i - 0.5 %}
        <i class="fas fa-star-half-alt"></i>
{% else %}
        <i class="far fa-star"></i>
    {% endif %}
{% endfor %}

Transform rating to stars

The number of voting stars will be filled in with yellow. And, I add a line of code to show a text in the case that there is no previous review.

The notification when there is no review.

I add some CSS to style the review as well.

Add CSS

Now, let’s check the result. It works as expected.

Display Average Rating in the Archive Page

I have already shown restaurants on an archive page using MB Views. Our work is calculating and displaying the average rating for each restaurant. I make use of the template for the archive page.

{% set reviews = mb.get_posts({
    post_type: 'review',
    posts_per_page: -1,
    meta_query: [
    {
        key: 'restaurant',
        value: post.ID,
        compare: '='
    }
    ]
}) %}
{% set total = 0 %}
{% for review in reviews %}
    {% set total = total + (review.rating|default(0)) %}
{% endfor %}
{% set count = reviews|length %}
{% set average = count > 0 ? (total / count)|round(1) : 0 %}

{% if count > 0 %}
<div class="star-rating">
    {% for i in 1..5 %}
        {% if average >= i %}
            <i class="fas fa-star"></i>
        {% elseif average >= i - 0.5 %}
            <i class="fas fa-star-half-alt"></i>
        {% else %}
            <i class="far fa-star"></i>
        {% endif %}
    {% endfor %}
    <span>{{ average }}/5 ({{ count }} Reviews)</span>
</div>
{% else %}
    <div class="no-rating">No Reviews</div>
{% endif %}

Code for displaying the average rating

As you can see, I also use the part to get all the reviews about the current restaurant.

Next, {% set total = 0 %} is to initialize this variable with the default value of 0. Then, it will be plus the value of the review.rating.

Our formula for calculating the average is: total / count. And the result will be shown with the rule of star. I use code similar to be in the previous step to transform the rating to stars. We loop through 5 stars. It shows a full star if the average is high enough, a half star if it’s in between, and an empty star otherwise.

That’s all.

You can also add some CSS for it.

Add CSS for the rating

And let’s check how it works. When you submit a review, the rating and number the review will be update.

The final result

Last Words

With just a few lines of code, you can display ratings, calculate averages, and make your website more interactive and trustworthy. Try applying the same logic to other content types and see how flexible MB Views can be. We have many applications of MB Views, so you can explore them now. Thanks for watching, and see you in the next tutorial!

Leave a Reply

Your email address will not be published. Required fields are marked *