Отзывы в WordPress без Плагинов

Рассмотрим, как сделать добавление и отправку отзывов в WordPress. При отправке отзыва пользователем он будет добавлен как запись со статусом «На утверждении». Отзыв будет размещён на сайте после проверки/модерации администратором. Рассмотрим также вариант, чтобы отзыв публиковался автоматически, после его отправки пользователем.

Файловая структура. Необходимые файлы.

  • Папка темы/
    • includes/
      • add_review.php
      • loop-review.php
    • js
      • add_review.js
    • functions.php
    • page-reviews.php

1. Форма отправки отзывов

Создадим форму отправки отзывов на сайте.

Обратите внимание на id формы add_review. Т.к. далее мы будем слушать событие submit - отправки формы.

<form id="add_review">
    <h3>Добавление отзыва</h3>
    <input type="text" name="name" placeholder="Ваше Имя" required>
    <textarea name="message" placeholder="Ваше сообщение" required></textarea>
    <div class="rating__group">
        <input class="rating__star" type="radio" name="rating" value="1" aria-label="Ужасно">
        <input class="rating__star" type="radio" name="rating" value="2" aria-label="Сносно">
        <input class="rating__star" type="radio" name="rating" value="3" aria-label="Нормально">
        <input class="rating__star" type="radio" name="rating" value="4" aria-label="Хорошо">
        <input class="rating__star" type="radio" name="rating" value="5" aria-label="Отлично" checked>
    </div>
</form>

Стилизация рейтинга:

/* Звёздный рейтинг для отзывов */
:root {
    --star_width: 22px;
    --star_bg: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" %3E%3Cpath style="fill:%23DADADA" d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/%3E%3C/svg%3E');
    --star_bg_fill: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" %3E%3Cpath style="fill:%236A1B9A" d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z"/%3E%3C/svg%3E');
}

.rating__group {
    position: relative;
    width: calc(var(--star_width) * 5);
    height: var(--star_width);
    background-image: var(--star_bg);
    background-size: var(--star_width) auto;
    background-repeat: repeat-x;
    background-color: transparent;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
}

.rating__star {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    position: absolute;
    top: 0;
    left: 0;
    height: var(--star_width);
    margin: 0;
    font-size: inherit;
    background-size: var(--star_width) auto;
    background-repeat: repeat-x;
    background-color: transparent;
    cursor: pointer;
    opacity: 1;
    border: none;
    border-radius: 0;
    transition: 0.2s;
}

.rating__star:focus {
    outline: none;
}

.rating__star:checked,
.rating__star:hover {
    background-image: var(--star_bg_fill);
    width: var(--star_width);
    height: var(--star_width);
    background-size: var(--star_width);
}

.rating__star:hover~.rating__star {
    background-image: var(--star_bg);
}

.rating__star:nth-child(1) {
    width: var(--star_width);
    z-index: 5;
}

.rating__star:nth-child(2) {
    width: calc(var(--star_width)* 2);
    z-index: 4;
}

.rating__star:nth-child(3) {
    width: calc(var(--star_width)* 3);
    z-index: 3;
}

.rating__star:nth-child(4) {
    width: calc(var(--star_width)* 4);
    z-index: 2;
}

.rating__star:nth-child(5) {
    width: calc(var(--star_width)* 5);
    z-index: 1;
}

2. Создание произвольного типа записи «Отзывы»

Создадим произвольный тип записи для отзывов в functions.php:

/**
 * Новый тип записи - «Отзывы»
**/
add_action( "init", "register_post_type_reviews" );
function register_post_type_reviews(){
    register_post_type("reviews", array(
        "label"  => null,
        "labels" => [
            "name"               => "Отзывы",
            "singular_name"      => "Отзыв",
            "add_new"            => "Добавить отзыв",
            "add_new_item"       => "Добавление отзыва",
            "edit_item"          => "Редактирование отзыва",
            "new_item"           => "Новый отзыв",
            "view_item"          => "Смотреть отзыв",
            "search_items"       => "Искать отзывы",
            "not_found"          => "Не найдено",
            "not_found_in_trash" => "Не найдено в корзине",
            "menu_name"          => "Отзывы",
        ],
        "description"            => "Отзывы",
        "exclude_from_search"    => false,
        "public"                 => true,
        "capability_type"        => "page",
        "hierarchical"           => false,
        "show_in_menu"           => null,
        "show_in_rest"           => null,
        "rest_base"              => null,
        "menu_position"          => null,
        "menu_icon"              => "dashicons-format-status",
        "supports"               => [
            "title",
            "editor",
            // "excerpt",
            // "trackbacks",
            // "custom-fields",
            // "comments",
            // "revisions",
            // "thumbnail",
            // "author",
            // "page-attributes",
        ],
        "has_archive"         => false,
        "rewrite"             => true,
        "query_var"           => true,
    ) );
}

/**
 * Уведомления о новых неопубликованных отзывах
**/
add_action( "admin_menu", "add_user_menu_bubble" );
function add_user_menu_bubble() {
    global $menu;

    $count = wp_count_posts("reviews")->pending; # на утверждении
    if ($count) {
        foreach ($menu as $key => $value) {
            if ( $menu[$key][2] == "edit.php?post_type=reviews" ) {
                $menu[$key][0] .= "<span class="awaiting-mod"><span class="pending-count">".$count."</span></span>";
                break;
            }
        }
    }
}

3. Файл обработчик формы создания отзывов

Теперь нам необходимо создать файл-обработчик для нашей формы отправки отзывов. Назовём его add-review.js.

Или же вы можете добавить данный код в уже существующий файл js.

/**
 * Добавление отзыва
**/
$("#add_review").submit(function (e) {
    e.preventDefault();
    $.ajax({
        type: "POST",
        url: "/wp-content/themes/{Название вашей темы}/includes/add_review.php",
        data: $(this).serialize(),
        success: () => {
            console.log("Спасибо. Ваш отзыв отправлен.");
            $(this).trigger("reset"); // очищаем поля формы
        },
        error: () => console.log("Ошибка отправки.");
    });
});

4. Получение и добавление отзыва в базу

Теперь нам необходимо обработать отправленный отзыв на стороне сервера. Создадим файл add-review.php.

<?php
ini_set("display_errors", 1);
error_reporting(E_ALL);

// Подключаем необходимые файлы
require_once($_SERVER["DOCUMENT_ROOT"] . "/wp-load.php");
require_once(ABSPATH . "wp-admin/includes/image.php");
require_once(ABSPATH . "wp-admin/includes/file.php");
require_once(ABSPATH . "wp-admin/includes/media.php");

// Получение отправленных данных
$user_name    = trim($_POST["name"]);
$user_message = trim($_POST["message"]);
$user_rating  = trim($_POST["rating"]);
// $review_type = trim($_POST["review_type"]); # можно передать термин таксономии

$post_data = array(
    "post_author"   => 1,
    "post_status"   => "pending",               # статус - «На утверждении»
    "post_type"     => "reviews",               # тип записи - «Отзывы»
    "post_title"    => "Отзыв - " . $user_name, # заголовок отзыва
    "post_content"  => $user_message,           # текст отзыва
    // "tax_input" => ["{Название таксономии}" => array($review_type)],
);

// Вставляем запись в базу данных
$post_id = wp_insert_post($post_data);

// Добавляем остальные поля
update_field("rejting", $user_rating, $post_id); # рейтинг
update_field("name", $user_name, $post_id);      # имя

// Необходимо для записи таксономии «tax_input»
// wp_set_object_terms( $post_id, $review_type, "{Название таксономии}" );

Чтобы отправленный отзыв публиковался незамедлительно, измените "post_status" на "publish".

Последние две строчки обновляют произвольные поля, созданные, например, в Advanced Custom Fields.

rejting, name - это имена произвольных полей ACF.

А текст отзыва мы записываем в текст записи WordPress.

5. Вывод отзывов

Теперь нам осталось вывести опубликованные отзывы на соответствующей странице, пусть это будет шаблон page-reviews.php - страница с отзывами.

Выведем отзывы с помощью WP_Query.

<?php
$mypost_Query = new WP_Query( array(
    "post_type"      => "reviews", # тип записи
    "post_status"    => "publish", # статус записи
    "posts_per_page" => -1,        # количество (-1 - все)
) );

if ( $mypost_Query->have_posts() ) {
    while ( $mypost_Query->have_posts() ) { $mypost_Query->the_post();

        get_template_part("./includes/loop-review"); // шаблон отзыва

    } wp_reset_postdata(); // "сброс"

} else { echo "<p>Извините, пока нет отзывов...</p>"; }

Шаблон отзыва WordPress

Пример шаблона отзыва loop-review.php.

<div class="review-item">
    <div class="review-item__name"><?php the_field("name"); ?></div>
    <div class="rating">
        <?php for ($r = 1; $r <= 5; $r++) { ?>
            <?php if (get_field("rejting") < $r) { ?>
                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
                    <path style="fill:#DADADA" d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z" />
                </svg>
            <?php } else { ?>
                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
                    <path style="fill:#EC3955" d="M12 .587l3.668 7.568 8.332 1.151-6.064 5.828 1.48 8.279-7.416-3.967-7.417 3.967 1.481-8.279-6.064-5.828 8.332-1.151z" />
                </svg>
            <?php } ?>
        <?php } ?>
    </div>
    <time class="review-item__date"><?php the_date("j.n.Y"); ?></time>
    <div class="review-item__text"><?php the_content(); ?></div>
</div>
  • <?php the_field("name"); ?> - выводим имя человека, написавшего отзыв;
  • <?php get_field("rejting"); ?> - получение рейтинга;
  • <?php the_date("j.n.Y"); ?> - вывод даты публикации отзыва;
  • <?php the_content(); ?> - вывод текста отзыва.