Скрипт звёздного рейтинга для сайта

Александр Мальцев
Александр Мальцев
42K
75
Скрипт звёздного рейтинга для сайта
Содержание:
  1. Обзор скрипта звёздного рейтинга
  2. Подключение скрипта звёздного рейтинга к сайту
  3. Настройка скрипта звёздного рейтинга
  4. Исходные коды звёздного рейтинга
  5. Комментарии

В этой статье рассмотрим скрипт рейтинга в виде звёзд, построенный на PHP и MySQL, и работающий без обновления страницы.

Обзор скрипта звёздного рейтинга

Скрипт рейтинга может применяться для оценки статей, услуг, товаров, видео, картинок и прочего материала на сайте в виде звёзд. С его помощью можно узнать среднюю оценку пользователей.

Этот скрипт можно привязать к любому материалу. Осуществляется это посредством указания ему некоторого идентификатора посредством атрибута data-id. На одну страницу можно добавить любое количество рейтингов.

Скрипт доступен в виде исходных кодов. Проект этого звёздного рейтинга расположен на GitHub.

Последняя версия данного скрипта - 1.0.4. Эта версия доступна по этой ссылке.

Проект реализован с использованием MySQL, PHP, JavaScript и CSS. При этом скрипт работает полностью через AJAX. Это означает, что его очень просто установить на сайт. Для этого достаточно к страницам просто подключить CSS и JavaScript файлы.

Скрипт звёздного рейтинга по умолчанию имеет защиту от накрутки по IP. Если она не нужна, то её можно отключить. Отметка рейтингов, пользователь которым выставил оценку сохраняется у него на устройстве в LocalStorage. Cookie в этом скрипте не используются.

Изображения звёздочек в этом скрипте выполнено с помощью SVG графики.

По умолчанию данный скрипт настроен на выставления оценки от 1 до 5. Но при необходимости вы можете установить любое другое количество звёзд.

Подключение скрипта звёздного рейтинга к сайту

Основные этапы:

  • создать таблицы в базе данных MySQL
  • поместить «process_star_rating.php» в некоторую папку проекта и указать в нём данные для подключения к базе данных;
  • подключить «star_rating.css» и «star_rating.js» к страницам сайта; указать в «star_rating.js» URL к «process_star_rating.php»;
  • вставить HTML-код рейтинга в необходимые места страниц сайта; задать им идентификатор с помощью атрибута data-id.

Создание таблиц в базе данных

Для работы звёздного рейтинга необходимо создать в базе данных MySQL две таблицы: star_rating и star_rating_ip.

Это действие, например можно выполнить с помощью инструмента phpmyadmin.

Для этого в phpmyadmin перейдите в вашу базу данных, нажмите на вкладку SQL и вставьте это содержимое:

CREATE TABLE `star_rating` (
  `id` int(10) UNSIGNED NOT NULL,
  `rating_id` varchar(20) NOT NULL,
  `rating_avg` float NOT NULL,
  `total_votes` int(10) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `star_rating_ip` (
  `id` int(10) UNSIGNED NOT NULL,
  `rating_id` int(10) UNSIGNED NOT NULL,
  `rating_value` tinyint(2) UNSIGNED NOT NULL,
  `rating_ip` varchar(16) NOT NULL DEFAULT '0.0.0.0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `star_rating`
  ADD PRIMARY KEY (`id`);
ALTER TABLE `star_rating_ip`
  ADD PRIMARY KEY (`id`),
  ADD KEY `rating_id` (`rating_id`);

ALTER TABLE `star_rating`
  MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `star_rating_ip`
  MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;

Нажмите на кнопку «Вперёд».

Создание таблиц для звёздного рейтинга с использованием инструмента phpmyadmin

Таблица star_rating является основной. Она состоит из следующих полей:

  • id – первичный ключ, его значение будет генерироваться автоматически (AUTO_INCREMENT);
  • rating_id – текстовый идентификатор рейтинга, его значение будет определять в HTML с помощью атрибута data-id;
  • rating_avg – среднее значение рейтинга;
  • total_votes – количество пользователей, поставивших оценку.

Таблица star_rating_ip является дополнительной. Она предназначена для хранения IP адресов пользователей. Данная таблица используется для определения того поставил ли оценку пользователь с данным IP за этот материал или нет. Она применяется для защиты рейтинга от накрутки.

Эта таблица состоит из следующих полей:

  • id – первичный ключ, его значение будет генерироваться автоматически (AUTO_INCREMENT);
  • rating_id – будет определять с каким id таблицы star_rating будет связана эта запись;
  • rating_value – значение рейтинга, установленного пользователем;
  • rating_ip – IP пользователя.

Настройка и загрузка на сайт PHP скрипта

Для того чтобы PHP файл мог осуществлять запросы к созданным таблицам, в него необходимо внести ваши настройки для подключения к базе данных:

const
  DB_HOST = 'localhost', // хост
  DB_NAME = 'mydb', // имя базы данных
  DB_CHARSET = 'utf8', // кодировка
  DB_USER = 'root', // имя пользователя MySQL
  DB_PASSWORD = '', // пароль пользователя MySQL
  MAX_RATING = 5,
  IS_CHECK_IP = true;

После сохранения настроек, переместите PHP файл «process_star_rating.php» в любую папку вашего проекта.

Включать «process_star_rating.php» в страницы этого сайта не нужно, т.к. этот звёздный рейтинг работает исключительно через AJAX.

Подключение CSS и JavaScript. Настройка URL к PHP файлу

Третий этап – это подключить к своим страницам файлы «star_rating.css» и «star_rating.js».

...
<link rel="stylesheet" href="star_rating.css">
...
<script src="star_rating.js"></script>

При желании вместо этого вы можете включить их содержимое в свои файлы.

Файл «star_rating.css» содержит стили (оформление рейтинга), а «star_rating.js» – логику для обновления данных рейтинга на странице как после загрузки страницы, так и после выполнения оценки. Файл «star_rating.js» написан на JavaScript с применением библиотеки jQuery.

Перед подключением «star_rating.js» его необходимо отредактировать, а именно указать в нём URL к файлу «process_star_rating.php», которое хранится в переменной processURL.

Значение переменной processURL по умолчанию:

processURL = '/process_star_rating.php',

Вставка HTML-кода рейтинга в необходимые места страниц

Заключительный этап – это вставить HTML-код рейтинга в определённые места страницы и задать ему с помощью атрибута data-id уникальный идентификатор.

<!-- star rating data-id="page-1" -->
<div class="star-rating__container">
  <div class="star-rating__wrapper">
    <div class="star-rating__avg"></div>
      <div class="star-rating" data-id="page-1">
        <div class="star-rating__bg">
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
            <path fill="currentColor"
            d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z">
            </path>
          </svg>
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
            <path fill="currentColor"
            d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z">
            </path>
          </svg>
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
            <path fill="currentColor"
            d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z">
            </path>
          </svg>
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
            <path fill="currentColor"
            d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z">
            </path>
          </svg>
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
            <path fill="currentColor"
            d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z">
            </path>
          </svg>
        </div>
        <div class="star-rating__live">
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="1">
            <path fill="currentColor"
            d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z">
            </path>
          </svg>
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="2">
            <path fill="currentColor"
            d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z">
            </path>
          </svg>
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="3">
            <path fill="currentColor"
            d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z">
            </path>
          </svg>
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="4">
            <path fill="currentColor"

            d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z">
            </path>
          </svg>
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="5">
            <path fill="currentColor"
            d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z">
            </path>
          </svg>
        </div>
      </div>
    <div class="star-rating__votes"></div>
  </div>
</div>

Настройка скрипта звёздного рейтинга

Рассмотрим решения некоторых вопросов для адаптации этого рейтинга под свой проект.

1.Как отключить ограничения по IP?

Для отключения проверки пользователя по IP необходимо в файле «process_star_rating.php» установить константе IS_CHECK_IP значение false:

IS_CHECK_IP = false;

После этого возможность у пользователя оценить уже оценённый материал будет ограничено только данными находящимися в Local Storage.

2. Как изменить количество звёзд?

Как изменить количество звёзд в рейтинге, построенном с использованием PHP, MySQL, CSS, JavaScript и SVG

Для того чтобы изменить количество звёзд, например на 10, необходимо выполнить следующие действия.

Изменить HTML код, а именно добавить в каждый из элементов .star-rating__bg и .star-rating__live дополнительно по 5 элементов svg. Звёздам (элементам svg), находящихся в .star-rating__live установить соответствующее значение data-rating.

<div class="star-rating__container">
  <div class="star-rating__wrapper">
    <div class="star-rating__avg"></div>
    <div class="star-rating" data-id="page-8">
      <div class="star-rating__bg">
        <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
        <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
        <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
        <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
        <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
        <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
        <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
        <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
        <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
        <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
      </div>
      <div class="star-rating__live">
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="1"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="2"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="3"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="4"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="5"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="6"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="7"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="8"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="9"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="10"><path fill="currentColor" d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
      </div>
    </div>
    <div class="star-rating__votes"></div>
  </div>
</div>

В «star_rating.js» изменить значение переменной maxStars на 10:

maxStars = 10,

В «process_star_rating.php» изменить значение константы MAX_RATING на 10:

MAX_RATING = 10,

3. Как установить другой цвет звёздам?

Как изменить цвет звездам в рейтинге

Цвет звёздам задаётся в CSS:

.star-rating__bg {
  color: #e0e0e0; /* фоновый цвет звёздочек */
  display: flex;
}

.star-rating_active:hover .star-rating__live {
  overflow: auto;
  width: 100% !important;
  color: #e0e0e0; /* фоновый цвет звёздочек */
}

.star-rating__live {
  display: flex;
  color: #ffb74d; /* цвет звёздочек для указания текущего рейтинга */
  overflow: hidden;
  position: absolute;
  top: 0;
  left: 0;
}

.star-rating__item_active {
  color: #fb8c00; /* цвет звездочек при наведении на них */
  cursor: pointer;
  transition: color 0.1s ease-in-out;
}

Поэтому чтобы изменить цвет звёзд необходимо заменить данные значения на другие.

4. Как изменить размеры звёзд?

Установка размера звёздам выполняется с помощью CSS:

.star-rating__item {
  width: 32px;
  height: 32px;
  flex: 0 0 32px;
}

Чтобы уменьшить или увеличить размер звёзд вам нужно просто вместо 32px указать другое необходимое значение.

Например, 50px:

.star-rating__item {
  width: 50px;
  height: 50px;
  flex: 0 0 50px;
}

Исходные коды звёздного рейтинга

Скрипт звёздного рейтинга состоит из 3 файлов: «star_rating.css», «star_rating.js» и «process_star_rating.php»:

Содержимое файла «star_rating.css»:

.star-rating__container {
  display: inline-block;
}

.star-rating__wrapper {
  position: relative;
  display: flex;
}

.star-rating {
  display: inline-block;
  position: relative;
  user-select: none;
}

.star-rating__bg {
  color: #e0e0e0;
  display: flex;
}

.star-rating__live {
  display: flex;
  color: #ffb74d;
  overflow: hidden;
  position: absolute;
  top: 0;
  left: 0;
}

.star-rating_active:hover .star-rating__live {
  overflow: auto;
  width: 100% !important;
  color: #e0e0e0;
}

.star-rating__item_active {
  color: #fb8c00;
  cursor: pointer;
  transition: color 0.1s ease-in-out;
}

.star-rating__item {
  width: 32px;
  height: 32px;
  flex: 0 0 32px;
}

.star-rating__avg {
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  text-align: center;
  width: 2em;
}

.star-rating__votes {
  display: flex;
  align-items: center;
  justify-content: center;
  padding-left: 0.5em;
  font-size: 0.875em;
}

Содержимое файла «star_rating.js»:

$(function() {
  var
    processURL = '/process_star_rating.php',
    maxStars = 5,
    output = [],
    ratingStarClass = '.star-rating_active .star-rating__item';
  if (localStorage.getItem('star_rating')) {
    output = JSON.parse(localStorage.getItem('star_rating'));
  }
  $('.star-rating').each(function () {
    var
      _this = this,
      ratingId = $(_this).attr('data-id');
    $.post(processURL, { 'action': 'get_rating', 'id': ratingId })
      .done(function (data) {
        if (data['result'] === 'success') {
          var
            ratingAvg = parseFloat(data['data']['rating_avg']),
            totalVotes = data['data']['total_votes'];
          $(_this).find('.star-rating__live').css('width', ratingAvg.toFixed(1) / maxStars * 100 + '%');
          $(_this).closest('.star-rating__wrapper').find('.star-rating__avg').text(ratingAvg.toFixed(1));
          $(_this).closest('.star-rating__wrapper').find('.star-rating__votes').text('оценок: ' + totalVotes);
          if (data['data']['is_vote'] !== undefined) {
            if (data['data']['is_vote'] === false) {
              if (output.indexOf(ratingId) < 0) {
                $(_this).addClass('star-rating_active');
              }
            }
          } else {
            if (output.indexOf(ratingId) < 0) {
              $(_this).addClass('star-rating_active');
            }
          }
        }
      });
  });

  var starRatingItems = $('.star-rating__live .star-rating__item');
  starRatingItems.on('mouseover', function () {
    var
      rating = $(this).attr('data-rating'),
      items = $(this).closest('.star-rating__live').find('.star-rating__item');
    if (!$(this).closest('.star-rating').hasClass('star-rating_active')) {
      return;
    }
    items.each(function (index, element) {
      if (index < rating) {
        if (!$(element).hasClass('star-rating__item_active')) {
          $(element).addClass('star-rating__item_active');
        } else {
          if ($(element).hasClass('star-rating__item_active')) {
            $(element).removeClass('star-rating__item_active');
          }
        }
      }
    })
  });

  starRatingItems.on('mouseout', function () {
    if (!$(this).closest('.star-rating').hasClass('star-rating_active')) {
      return;
    }
    $(this).closest('.star-rating__live').find('.star-rating__item').removeClass('star-rating__item_active');
  });

  $(document).on('click', ratingStarClass, function (e) {
    e.preventDefault();
    var
      _this = this,
      ratingId = $(_this).closest('.star-rating').attr('data-id'),
      rating = $(_this).attr('data-rating');
    $.post(processURL, { 'action': 'set_rating', 'id': ratingId, 'rating': rating })
      .done(function (data) {
        if (!$.isEmptyObject(data)) {
          if (data['result'] === 'success') {
            var
              ratingAvg = parseFloat(data['data']['rating_avg']),
              totalVotes = data['data']['total_votes'],
              output = [];
            $(_this).closest('.star-rating').removeClass('star-rating_active')
              .find('.star-rating__item_active').removeClass('star-rating__item_active')
              .end().find('.star-rating__live').css('width', ratingAvg.toFixed(1) / maxStars * 100 + '%');
            $(_this).closest('.star-rating__wrapper')
              .find('.star-rating__avg').text(ratingAvg.toFixed(1))
              .end().find('.star-rating__votes').text('оценок: ' + totalVotes);
            if (localStorage.getItem('star_rating')) {
              output = JSON.parse(localStorage.getItem('star_rating'));
            }
            if (output.indexOf(ratingId) < 0) {
              output.push(ratingId);
            }
            localStorage.setItem('star_rating', JSON.stringify(output));
          }
        }
      });
  });
});

Содержимое файла «process_star_rating.php»:


<?php

const
DB_HOST = 'localhost',
DB_NAME = 'mydb',
DB_CHARSET = 'utf8',
DB_USER = 'root',
DB_PASSWORD = '',
MAX_RATING = 5,
IS_CHECK_IP = false;

function log_write($message)
{
  $log = date('d.m.Y H:i:s') . PHP_EOL . $message . PHP_EOL . '-------------------------' . PHP_EOL;
  file_put_contents('error.log', $log, FILE_APPEND);
}

function getIp()
{
  $keys = [
    'HTTP_CLIENT_IP',
    'HTTP_X_FORWARDED_FOR',
    'REMOTE_ADDR'
  ];
  foreach ($keys as $key) {
    if (!empty($_SERVER[$key])) {
      $ip = trim(end(explode(',', $_SERVER[$key])));
      if (filter_var($ip, FILTER_VALIDATE_IP)) {
        return $ip;
      }
    }
  }
}

if (empty($_SERVER['HTTP_X_REQUESTED_WITH']) || $_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest') {
  exit(json_encode($output));
}

if ($_SERVER['REQUEST_METHOD'] != 'POST') {
  exit(json_encode($output));
}

$output['result'] = 'error';

$count = 0;
$totalVotes = 1;
if (empty($_POST['id'])) {
  log_write('Не передан id!');
  exit(json_encode($output));
}
$ratingId = filter_var($_POST['id'], FILTER_SANITIZE_STRING);
if (strlen($ratingId) == 0) {
  log_write('Параметр id имеет в качестве значения пустую строку!');
  exit(json_encode($output));
}

try {
  $conn = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=' . DB_CHARSET, DB_USER, DB_PASSWORD);
  $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
  log_write('Подключение не удалось: ' . $e->getMessage());
  exit(json_encode($output));
}

switch ($_POST['action']) {
  case 'get_rating':
    $output['data'] = [
      'rating_avg' => 0,
      'total_votes' => 0
    ];
    try {
      $sql = 'SELECT id, rating_avg, total_votes FROM star_rating WHERE rating_id = :rating_id LIMIT 1';
      $result = $conn->prepare($sql);
      $data = ['rating_id' => $ratingId];
      $result->execute($data);
      $row = $result->fetch(PDO::FETCH_ASSOC);
      if ($row) {
        $output['data'] = [
          'rating_avg' => $row['rating_avg'],
          'total_votes' => $row['total_votes']
        ];
        if (IS_CHECK_IP == true) {
          $sql = 'SELECT count(*) FROM star_rating_ip WHERE rating_id = :rating_id AND rating_ip = :rating_ip';
          $result = $conn->prepare($sql);
          $data = ['rating_id' => $row[id], 'rating_ip' => getIp()];
          $result->execute($data);
          $countRows = $result->fetchColumn();
          if ($countRows == 0) {
            $output['data']['is_vote'] = false;
          } else {
            $output['data']['is_vote'] = true;
          }
        }
      }
    } catch (PDOException $e) {
      log_write('Ошибка выборки данных: ' . $e->getMessage());
      break;
    }
    $output['result'] = 'success';
    break;

  case 'set_rating':
    if (empty($_POST['rating'])) {
      log_write('Не получено значение рейтинга!');
      break;
    }
    $id = 0;
    $rating = (int)$_POST['rating'];
    if ($rating < 1 || $rating > MAX_RATING) {
      log_write('Полученное значение рейтинга ' . $rating . ' лежит вне допустимого диапазона!');
      break;
    }
    $ratingAvg = $rating;
    try {
      $sql = 'SELECT id, rating_avg, total_votes FROM star_rating WHERE rating_id = :rating_id LIMIT 1';
      $result = $conn->prepare($sql);
      $data = ['rating_id' => $ratingId];
      $result->execute($data);
      $row = $result->fetch(PDO::FETCH_ASSOC);
      if ($row) {
        $count = 1;
        $id = $row['id'];
        $ratingAvg = $row['rating_avg'];
        $totalVotes = $row['total_votes'];
      }
    } catch (PDOException $e) {
      log_write('Ошибка выборки данных: ' . $e->getMessage());
      break;
    }

    if ($count == 0) {
      try {
        $result = $conn->prepare('INSERT INTO star_rating (rating_id, rating_avg, total_votes) VALUES (:rating_id, :rating_avg, :total_votes)');
        $result->execute(['rating_id' => $ratingId, 'rating_avg' => $ratingAvg, 'total_votes' => $totalVotes]);
        if (IS_CHECK_IP == true) {
          try {
            $sql = 'SELECT id FROM star_rating WHERE rating_id = :rating_id LIMIT 1';
            $result = $conn->prepare($sql);
            $data = ['rating_id' => $ratingId];
            $result->execute($data);
            $row = $result->fetch(PDO::FETCH_ASSOC);
            if ($row) {
              try {
                $result = $conn->prepare('INSERT INTO star_rating_ip (rating_id, rating_value, rating_ip) VALUES (:rating_id, :rating_value, :rating_ip)');
                $result->execute(['rating_id' => $row['id'], 'rating_value' => $rating, 'rating_ip' => getIp()]);
              } catch (PDOException $e) {
                log_write('Ошибка добавления новой записи в таблицу star_rating_ip: ' . $e->getMessage());
                break;
              }
            }
          } catch (PDOException $e) {
            log_write('Ошибка выборки данных: ' . $e->getMessage());
            break;
          }
        }
      } catch (PDOException $e) {
        log_write('Ошибка добавления новой записи в базу: ' . $e->getMessage());
        break;
      }
    } else {
      $ratingAvg = ($ratingAvg * $totalVotes + $rating) / ($totalVotes + 1);
      $totalVotes = $totalVotes + 1;
      if (IS_CHECK_IP == true) {
        $ip = getIp();
        $sql = 'SELECT count(*) FROM star_rating_ip WHERE rating_id = :rating_id AND rating_ip = :rating_ip';
        $result = $conn->prepare($sql);
        $data = ['rating_id' => $id, 'rating_ip' => $ip];
        $result->execute($data);
        $countRows = $result->fetchColumn();
        if ($countRows > 0) {
          break;
        }
        try {
          $result = $conn->prepare('INSERT INTO star_rating_ip (rating_id, rating_value, rating_ip) VALUES (:rating_id, :rating_value, :rating_ip)');
          $result->execute(['rating_id' => $id, 'rating_value' => $rating, 'rating_ip' => $ip]);
        } catch (PDOException $e) {
          log_write('Ошибка добавления новой записи в таблицу star_rating_ip: ' . $e->getMessage());
          break;
        }
      }
      $sql = 'UPDATE star_rating SET rating_avg=:rating_avg, total_votes=:total_votes WHERE rating_id=:rating_id';
      $data = [
        'rating_id' => $ratingId,
        'rating_avg' => $ratingAvg,
        'total_votes' => $totalVotes
      ];
      try {
        $conn->prepare($sql)->execute($data);
      } catch (PDOException $e) {
        log_write('Ошибка добавления записи с rating_id = ' . $ratingId . ': ' . $e->getMessage());
        break;
      }
    }

    $output['result'] = 'success';

    $output['data'] = [
      'rating_avg' => $ratingAvg,
      'total_votes' => $totalVotes
    ];
    break;
}

header('Content-Type: application/json');
exit(json_encode($output));

Комментарии: 75

  1. G.Na4alnik
    G.Na4alnik
    2022-08-10 17:09:41
    Рейтинг отлично работает, но вылезла проблема с разметкой. ГуглВебмастер ругается на разметку с нулевым значением. Может как-то можно не показывать разметку если рейтинга еще нет или по умолчанию ставить оценку, например 4? Очень нужно.
  1. Алексей
    Алексей
    2022-06-20 16:04:08
    Здравствуйте. Почему-то, звезды заполняются целыми. Без всяких 4.5
    1. Алексей
      Алексей
      2022-06-20 16:08:23
      И как сделать, что б возможность голосовать была в одном месте, а вывод результата в другом, (допустим, голосует в комментариях, а результат выводиться на странице статьи.)
  2. Alex DOM
    Alex DOM
    2021-11-16 16:47:58
    А почему такой классный рейтинг не запихнули в FiveStarRating?
    Было бы очень крутое решение.
    1. Александр Мальцев
      Александр Мальцев
      2021-11-18 13:26:54
      Спасибо за совет! Появится время, обновлю FiveStarRating.
  3. Денис Картинкин
    Денис Картинкин
    2021-10-13 04:34:32
    Материал понятен, вроде всё просто. А почему нет примера? И нет такого на этой странице?
    Мой опыт показал, в таких случаях могу потратить время на воплощение, а результат меня огорчит.
    1. MCrabs
      MCrabs
      2021-10-07 18:28:04
      process_star_rating.php почему то если ввести адрес, то выдает {«result»:«error»}?
      Какие права надо предоставить для файла? 744?
      Ипуть к файлу php в js указывать полный или можно относительный?
      1. Александр Мальцев
        Александр Мальцев
        2021-10-09 10:00:24
        Для «process_star_rating.php» достаточно прав 644. Напрямую запустить данный файл не получится, к нему необходимо обращаться только через AJAX. На вход он требует определённые данные, которые он получает из массива $_POST.
        Путь к файлу можно указать как абсолютный, так и относительный. Тут как вам удобнее:
        var processURL = '/process_star_rating.php';
    2. MCrabs
      MCrabs
      2021-10-07 16:28:10
      Александр, здравствуйте.
      Ни как не получается сделать что бы все работало с небольшими изменениями.
      Мне нужно что бы data-id подставлялся из url. потому что много страниц.
      Вот рабочий скрипт как я делаю (вставляю в разметку этот скрипт при этом в разметке удаляю значения data-id )
      <script>
      	document.addEventListener("DOMContentLoaded", () => {
         
      		let location = window.location.href; console.log(location);
      		let elem = document.getElementById('rund');//ищем ранее добавленый id rund в разметке
      			const url = new URL(location);
      			url.pathname;
      		elem.dataset.id = url.pathname.slice(24);//обрезаем 24 символа после домена и присваиваем этот остаток url в data-id
      		console.log(elem.dataset.id);// проверка
      		});
      	  </script>
      но с этим скриптом перестает работать.
      Если добавить в star_rating.js
      document.addEventListener("DOMContentLoaded", () => {-кот-----)}

      То пропадает количество проголовавших.
      Помогите пожалуйста.
      Тока начал учиться JS и не совсем понимаю.
      То ли php файл раньше обрабатывает страницу чем этот скрипт.
      если добавить просто data-id=«tata», то все работает.
      Помогите пожалуйста.
      1. MCrabs
        MCrabs
        2021-10-07 16:44:40
        Вот нашел
        sleep(int $seconds): int
        Откладывает исполнение программы на число секунд, указанное в параметре seconds.
        Но как это реализовать?
      2. MCrabs
        MCrabs
        2021-10-07 17:07:34
        Ой, чета все заработало. Спасибо за вашу статью.
      3. MCrabs
        MCrabs
        2021-10-07 19:29:21
        Но как то через раз работает. То загружается, то после перезагрузки.
      4. Александр Мальцев
        Александр Мальцев
        2021-10-09 09:53:40
        Привет!
        1. В базе данных колонке «rating_id» установите «varchar(255)» или больше в зависимости от того, какой у вас самый длинный URL.
        2. Добавьте в начало файла «star_rating.js» сразу после объявления переменных эту строчку:
        $('.star-rating').attr('data-id', location.pathname);
        На Github полный код звездного рейтинга через URL находится в папке «via-url».
      5. MCrabs
        MCrabs
        2021-10-09 10:49:32
        Спасибо, сделал почти как Вы сказали. Вставил после объявления функции.
        Спасибо.
        Как бы Вам позвонить? Есть маленькие трудности на сайте с автоматизацией. Как я говорил я только в самом начале обучения и мне нужна помощь.
    3. MCrabs
      MCrabs
      2021-10-05 12:01:57
      Здравствуйте. Почему то нет количества проголосовавших. как исправить подскажите пожалуйста
      1. Александр Мальцев
        Александр Мальцев
        2021-10-09 10:03:32
        Здравствуйте! Может быть, вы что-то изменили или проверьте стили. На HTML странице в элементе «star-rating__votes_count» есть данные?
    4. MCrabs
      MCrabs
      2021-10-03 09:43:35
      Добрый день не подскажите как сделать что бы (class=«star-rating» data-id=«page-8» + ( id=" rund")) data-id цеплялся из урл. Автоматом примерно так
      let location = window.location.href;
      let elem = document.getElementById('rund');
      //ищем ранее добавленый id rund в разметке
      const url = new URL(location)
      url.pathname;
      url.pathname.slice(24);
      Если скрипт разместить в разметке он подставляет data-id но в папке error пишет нет ид.
      1. MCrabs
        MCrabs
        2021-10-03 10:51:52
        не дописал elem.dataset.id = url.pathname.slice(24);
      2. MCrabs
        MCrabs
        2021-10-03 12:14:27
        вот так вроде работает может кому пригодиться
        document.addEventListener("DOMContentLoaded", () => {
           
        		let location = window.location.href; console.log(location);
        		let elem = document.getElementById('rund');//ищем ранее добавленый id rund в разметке
        			const url = new URL(location);
        			url.pathname;
        		elem.dataset.id = url.pathname.slice(24);
        		console.log(elem.dataset.id);
        		});
      3. MCrabs
        MCrabs
        2021-10-03 12:51:15
    5. Сергій
      Сергій
      2021-01-28 07:40:28
      Добрый день. Подскажите как сделать так чтобы допустим из нескольких рейтингов пользователь мог выбрать только 1 рейтинг из списка, а остальные заблокировались.
      1. Цыганок Анастасия Сергеевна
        Цыганок Анастасия Сергеевна
        2020-09-30 11:58:32
        Александр, добрый день. Большое спасибо за статью. Очень полезная и написана доступно. Но я столкнулась с такой проблемой. Все настроила и под админом все работает, а вот под обычным пользователем все звездочки желтые и данные по рейтингу не показываются. Я так понимаю что под пользователем не запускается process_star_rating.php. Подскажите, пожалуйста как это исправить?
        1. Александр Мальцев
          Александр Мальцев
          2020-09-30 14:00:27
          Здравствуйте! Спасибо! Для этого необходимо поместить файл «process_star_rating.php» в такое место сайта, чтобы он был доступен для обычного пользователя с фронтенда. Также попробуйте проверить в режиме инкогнито.
        2. Цыганок Анастасия Сергеевна
          Цыганок Анастасия Сергеевна
          2020-10-01 07:08:22
          Я разместила все три файла в корневом каталоге сайта, остальные же файлы от туда отрабатывают. В режиме инкогнито работает. А в обычном режиме нет.
        3. Цыганок Анастасия Сергеевна
          Цыганок Анастасия Сергеевна
          2020-10-01 15:37:19
          После нажатия Ctrl+F5 везде перестало работать :(
        4. Александр Мальцев
          Александр Мальцев
          2020-10-01 15:51:34
          Так это защита от накрутки. После того как пользователь проголосовал, в его браузер сохраняется соответствующая информация (по умолчанию в LocalStorage). Второй раз проголосовать за этот материал он уже не может. Кроме этой защиты также ещё можно включить защиту по IP (по умолчанию она отключена).
        5. Цыганок Анастасия Сергеевна
          Цыганок Анастасия Сергеевна
          2020-10-01 16:48:59
          Это хорошо что есть защита. Но почему не показывается рейтинг, а просто изображены звездочки желтого цвета?
        6. Александр Мальцев
          Александр Мальцев
          2020-10-03 01:06:11
          Тогда нужно разбираться из-за чего это происходит. Посмотрите, что возвращает сервер, если он возвращает всё правильно, то тогда нужно искать проблему на клиенте. Например, на странице у вас могут быть подключены стили, которые переопределяют то, что задано в «star_rating.css» или что-то другое.
        7. Цыганок Анастасия Сергеевна
          Цыганок Анастасия Сергеевна
          2020-10-03 14:24:48
          А на мобильном тоже из-за этого может не работать?
        8. Александр Мальцев
          Александр Мальцев
          2020-10-03 14:36:29
          Конечно. Откройте инструменты разработчика в браузере и посмотрите что у вас приходит с сервера, есть ли элементы с рейтингом на странице, какие стили к ним применены и т.д.
        9. Цыганок Анастасия Сергеевна
          Цыганок Анастасия Сергеевна
          2020-10-04 06:55:08
          Можете посмотреть, пожалуйста? vseonline.info/
          Сама разобраться не могу :(
        10. Александр Мальцев
          Александр Мальцев
          2020-10-04 13:21:55
          Вам необходимо в файле «star_rating.js» указать протокол http (т.к. используете его), а не https.
          ...
          processURL = 'http://vseonline.info/process_star_rating.php',
          ...
          
        11. Цыганок Анастасия Сергеевна
          Цыганок Анастасия Сергеевна
          2020-10-06 19:18:12
          Спасибо большое за помощь. Всё получилось настроить. Правда я наоборот включила на сервере https.
        12. Александр Мальцев
          Александр Мальцев
          2020-10-08 13:18:02
          Рад, что получилось.
      2. Сергей
        Сергей
        2020-08-26 23:46:51
        Александр, приветствую! Столкнулся с такой проблемой: дублируется один и тот же рейтинг. Например, я ставлю пять звезд статье, однако этот же рейтинг дублируется на все остальные материалы, где есть возможность поставить оценку. Где может быть ошибка?
        1. Александр Мальцев
          Александр Мальцев
          2020-08-27 04:11:41
          Привет! Нужно установить для разных материалов разное значение атрибуту data-id.
        2. Сергей
          Сергей
          2020-08-27 13:33:01
          Спасибо за помощь!
      3. alexandr_k
        alexandr_k
        2020-04-26 22:50:39
        Доброго дня, подскажите, пожалуйста, как правильно подключить этот скрипт на Joomla 3?
        Файл process_star_rating.php на вкладке network имеет статус 403 forbidden.
        Спасибо
        1. alexandr_k
          alexandr_k
          2020-04-27 00:16:20
          по 403 ошибке вопрос решился.
          Но рейтинг не включается, вкладка network на файле process_star_rating.php показывает

          {«result»:«error»,«data»:{«rating_avg»:0,«total_votes»:0}}
        2. alexandr_k
          alexandr_k
          2020-04-27 00:30:23
          Нашел свой косяк, все работает. Скрипт очень полезный, большое спасибо.

          Но, все-таки, если можете, подскажите, пожалуйста, что нужно дописать, чтобы использовать подключение к базе данных средствами Джумлы, без указания имени и пароля?

        3. Александр Мальцев
          Александр Мальцев
          2020-04-27 15:02:26
          Отлично! Вам нужно подключить Joomla API к этому внешнему файлу. После этого доработать код используя её функции.
      4. Mish
        Mish
        2020-03-02 22:37:12
        Скажите пожалуйста как сделать «Вывод ресурсов с самым большим рейтингом», как тут: itchief.ru/lessons/modx-revo/modx-star-rating-for-articles-site
        1. Александр Мальцев
          Александр Мальцев
          2020-03-07 15:38:25
          Вы хотите это выполнить для MODX? Если да, то вам нужно из этого решения сначала сделать компонент для MODX. Ну или по крайней мере сгенерировать для него модель.
        2. Mish
          Mish
          2020-03-07 15:56:05
          Да на MODX. Ничего не понял = (
      5. Резников Сергей
        Резников Сергей
        2020-02-23 10:22:30
        здравствуйте!
        не могу настроить работу звездного рейтинга.
        вот код который на сайте.
                      <!-- --star-rating__container-- -->
        				<div class="star-rating__container">
        				  <div class="star-rating__wrapper"itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating">
        				    <div class="star-rating__avg" itemprop="ratingValue"></div>
        				      <div class="star-rating" data-id="page-'.$ids.'1">
        				        <div class="star-rating__bg">
        				          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor"d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
        				          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor"d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
        				          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor"d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
        				          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor"d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
        				          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor"d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
        				        </div>
        				        <div class="star-rating__live">
        				          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="1"><path fill="currentColor"d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
        				          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="2"><path fill="currentColor"d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
        				          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="3"><path fill="currentColor"d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
        				          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="4"><path fill="currentColor"d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
        				          <svg class="star-rating__item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-rating="5"><path fill="currentColor"d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"></path></svg>
        				        </div>
        				      </div>
        				    <div class="star-rating__votes"></div>
        				  </div>
        				</div>
                      <!-- --star-rating__container-- -->
                      <!-- footer -->
        <link href="../js/rating/with_aggregaterating/jquery-3.4.1.min.js" media="screen">
        <link href="../js/rating/with_aggregaterating/star_rating.js" media="screen">
            
        стили включены в style.css в header
        
        
        <!-- process_star_rating.php  -->
        const
        DB_HOST = 'localhost',
        DB_NAME = 'vistab_vistablog',
        DB_CHARSET = 'utf8',
        DB_USER = 'vistab',
        DB_PASSWORD = 'y76pK2ecKCbPNcI',
        MAX_RATING = 5,
        IS_CHECK_IP = true;
        
        <!-- star_rating.js  -->
        $(function () {
        
            var
                processURL = $global_href.'js/rating/with_aggregaterating/process_star_rating.php',
        
        
        отображается 5 желтых звезд и все. как статика
        1. Александр Мальцев
          Александр Мальцев
          2020-02-24 14:23:22
          Проверьте, есть ли какие ошибки в консоли браузере и на вкладке Network для «process_star_rating.php». Так же стоит проверить есть ли ошибки в файле error.log, а также ошибки error_log в Apache или другом веб-сервере, который вы используете. Может просто дело в версии PHP, обычно не тестирую скрипт на версии меньше 7.0.
        2. Резников Сергей
          Резников Сергей
          2020-02-25 21:20:33
          Добрый вечер! Посмотрел, лог ошибок пустой, PHP Version 7.3.14. Не пойму что не так
        3. Александр Мальцев
          Александр Мальцев
          2020-02-26 14:04:27
          А что в базе? Записи создаются?
        4. Резников Сергей
          Резников Сергей
          2020-02-26 14:10:12
          Обе базы пустые
        5. Александр Мальцев
          Александр Мальцев
          2020-02-26 14:21:58
          Проверьте по какому URL у вас достпен файл «process_star_rating.php» и задайте его в JavaScript файле:
          processURL = '/process_star_rating.php', 
          
        6. Резников Сергей
          Резников Сергей
          2020-02-26 14:29:52
          Если ввести в адресной строке адрес файла выводится {«result»:«error»}
        7. Александр Мальцев
          Александр Мальцев
          2020-02-26 14:50:21
          Посмотрите, что возвращает «process_star_rating.php» в браузере на вкладке Network.
        8. Резников Сергей
          Резников Сергей
          2020-02-26 14:57:22
          --------- Headers ---------
          general
          Request URL: http:------------------убрал-----------------/process_star_rating.php
          Request Method: GET
          Status Code: 200 OK
          Remote Address: 91.219.194.7:80
          Referrer Policy: no-referrer-when-downgrade
          
          Response Headers
          Connection: Upgrade, Keep-Alive
          Content-Encoding: gzip
          Content-Length: 38
          Content-Type: text/html; charset=UTF-8
          Date: Wed, 26 Feb 2020 11:51:35 GMT
          Keep-Alive: timeout=15, max=100
          Server: Apache
          Upgrade: h2,h2c
          Vary: Accept-Encoding,User-Agent
          X-Powered-By: PHP/7.3.14
          
          Request Headers
          Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
          Accept-Encoding: gzip, deflate
          Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7
          Cache-Control: max-age=0
          Connection: keep-alive
          Cookie: __utma=150660145.1318745452.1582714393.1582714393.1582714393.1; __utmc=150660145; __utmz=150660145.1582714393.1.1.utmccn=(direct)|utmcsr=(direct)|utmcmd=(none); fid=679de0fe-a998-4308-865f-a478f7f36de7; s=1; _ym_uid=1582714463341127256; _ym_d=1582714463; _ym_isad=2; tmr_lvid=dec317aeca9ca98a10094d75170989d7; tmr_lvidTS=1582714463080; dbl=aa8d3d87aa79428ea59c844cc783b956; fco2r3=aa8d3d87aa79428ea59c844cc783b956; last_visit=1582703677250::1582714477250; tmr_detect=0%7C1582714487788; tmr_reqNum=5
          Host: ---------------- убрал
          Upgrade-Insecure-Requests: 1
          User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36
          
          --------- Preview ---------
          {result: "error"}
          result: "error"
          
          --------- Response ---------
          {result: "error"}
          
        9. Александр Мальцев
          Александр Мальцев
          2020-02-26 15:03:49
          Он должен возвращать JSON. Сохраните файл «process_star_rating.php» в кодировке UTF-8 без BOM.
      6. Andrey
        Andrey
        2020-02-06 23:58:46
        Здравствуйте, подскажите пожалуйста, как можно заменить SVG на иконки к примеру от font awesome?
        1. Александр Мальцев
          Александр Мальцев
          2020-02-08 16:00:25
          Здравствуйте!
          Просто замените svg-графику на иконки Font Awesome:
          <div class="star-rating__container">
            <div class="star-rating__wrapper">
              <div class="star-rating__avg"></div>
              <div class="star-rating" data-id="page-1">
                <div class="star-rating__bg">
                  <i class="star-rating__item fas fa-star"></i>
                  <i class="star-rating__item fas fa-star"></i>
                  <i class="star-rating__item fas fa-star"></i>
                  <i class="star-rating__item fas fa-star"></i>
                  <i class="star-rating__item fas fa-star"></i>
                </div>
                <div class="star-rating__live">
                  <i class="star-rating__item fas fa-star" data-rating="1"></i>
                  <i class="star-rating__item fas fa-star" data-rating="2"></i>
                  <i class="star-rating__item fas fa-star" data-rating="3"></i>
                  <i class="star-rating__item fas fa-star" data-rating="4"></i>
                  <i class="star-rating__item fas fa-star" data-rating="5"></i>
                </div>
              </div>
              <div class="star-rating__votes">
                <div class="star-rating__votes_count"></div>
                <div class="star-rating__votes_message d-none">Оцени!</div>
              </div>
            </div>
          </div>
          
          После этого необходимо будет поправить стили, т.к. ширина изменится и размер звездочек уже нужно устанавливать с помощью font-size:
          .star-rating__item {
            width: 32px;
            height: 32px;
            font-size: 32px;
            flex: 0 0 32px;
          }
          ...
          
          Тут стили уже настраиваете так, как вам нужно.
      7. Павел
        Павел
        2020-01-16 11:51:11
        itemReviewed Необходимо указать значение для поля itemReviewed.
        Где и что необходимо вписать?
        1. Александр Мальцев
          Александр Мальцев
          2020-01-16 13:59:08
          А вы к какому объекту добавляете звёздочки?
        2. Павел
          Павел
          2020-01-16 14:07:52
          Вот страница с которой воюю. _http://bienvenidospb.com/tour-1-dia-por-san-petersburgo-en-espanol.html
          К Product
        3. Александр Мальцев
          Александр Мальцев
          2020-01-16 14:27:29
          У вас на страницу структурированные данные добавляются с помощью формата JSON-LD. В этом случае так делать нельзя, вам нужно семантическую разметку звёздочек тоже включить в JSON-LD.
        4. Павел
          Павел
          2020-01-16 15:09:13
          Изменил как у вас в примере. Проблема ушла. Спасибо за помощь!
          Но возник другой вопрос как сделать, чтобы значения ratingValue и reviewCount вставлялись автоматически? Сейчас они прописаны руками в нужные поля.
          если их удалить — возникают ошибки с разметкой.
        5. Александр Мальцев
          Александр Мальцев
          2020-01-16 15:32:16
          Они вставляются на страницу с помощью JavaScript. А как нужно?
        6. Павел
          Павел
          2020-01-16 15:53:03
          Если их не вставить вручную то почему при разметки они не видны
          _http://bienvenidospb.com/tour-2-dias-por-san-petersburgo-en-espanol.html
          Выдает 2 ошибки
        7. Александр Мальцев
          Александр Мальцев
          2020-01-17 12:50:08
          Инструмент тестирования Google не выполняет JavaScript как Googlebot.
          Поэтому ваш ajax-контент не отображается в инструменте.

          В этом случае для проверки семантической разметки вам необходимо просто скопировать отрисованный код страницы в инструмент и проверить его.

          На данный момент проверить, что Googlebot берёт этот код — это подождать и посмотреть, появиться ли он в отчёте структурированных данных Google или в поиске (в сниппетах).
      8. Игорь
        Игорь
        2019-11-19 11:33:26
        Отличная статья! Подскажите, а эти звезды индексируются Google? Знаете иногда под статьями при выдачи по запросу отображаются звезды рейтинга.
        1. Александр Мальцев
          Александр Мальцев
          2019-11-19 15:25:19
          Спасибо! Добавил в проект разметку schema.org/AggregateRating. С помощью неё Google будет индексировать звёзды и показывать их в выдачи.
          Райтинг с микроразметкой AggregateRating находится на GitHub и в архиве проекта в каталоге with_aggregaterating. Рейтинг без микроразметки schema.org находится в корне проекта.
        2. Игорь
          Игорь
          2019-11-19 16:47:32
          Вам спасибо за Ваш труд!
        3. radiooo
          radiooo
          2019-12-20 15:16:00
          Гугл не видит звезды, можно проверить на странице проверки структурированных данных
          https://search.google.com/structured-data/testing-tool/u/0/
        4. Александр Мальцев
          Александр Мальцев
          2019-12-21 03:40:01
          Их нужно добавить к какой-нибудь сущности, например, к товару. Этот пример добавлен на Github.
          Ссылка на проверку.
        5. Павел
          Павел
          2020-01-16 09:12:29
          Подскажите, пожалуйста, как их добавить?
        6. alexandr_k
          alexandr_k
          2020-04-27 12:06:07
          Доброго дня.
          В вашем примере после отрисовки кода itemprop=«ratingValue» сохраняется. А вот в скрипте по этой ссылке github.com/itchief/StarRating/archive/v.1.0.4.zip itemprop=«ratingValue» исчезает. При этом, itemprop=«reviewCount» остается.

        7. alexandr_k
          alexandr_k
          2020-04-27 13:12:50
          у меня глюк какой-то был, теперь не исчезает…
      9. Александр
        Александр
        2019-11-11 15:45:06
        Александр, здравствуйте! Отличное руководство, спасибо. Скажите а как в pdoTools и в mFilter2, сортировать по данному рейтингу? Как можно вывести оценку пользователя?

        И если возможно, есть ли какие преимущества данного способа в плане скорости работы, перед готовыми компонентами рейтинга, такими как LexRating и подобными, если теоретически?

        1. Александр Мальцев
          Александр Мальцев
          2019-11-12 03:08:05
          Привет!
          Это решение не связано с какой-то CMS. Его можно добавить на любой сайт, даже если он является статическим. Единственное требование — это наличие на хостинге поддержки PHP и MySQL.
          Чтобы этот звёздный рейтинг связать с какими-то объектами CMS, необходимо всё это конечно прописывать самостоятельно. Например, в MODX нужно будет просто создать компонент (модель для этих таблиц). После этого его можно будет использовать с pdoTools и mFilter2.
          Про оценку пользователя… Оценку пользователя можно сохранить в Local Storage, а затем её просто выводить. Если нужно сделать это решение именно для авторизированных пользоватей MODX, то это дело конечно нужно дописывать.

          Про быстродействие… Решение не связанное с CMS, если оно корректно написанное, в любом случае будет работать быстрее. Т.к. не будут выполняться различные проверки и другие механизмы CMS.
          Если заметили, то это решение выполняется только после загрузки страницы через AJAX. Оно вообще не увеличивается время парсинга страницы. Это первое отличие, если конечно его как-то сравнивать с LexRating. Второе — это то, что звёздочки выполнены с помощью SVG графики. Это означает что звёздочки будут выглядеть отлично на любом устройстве. Кроме этого, это решение позволяет очень просто изменить цвет и размер звёздочек.
        2. Александр
          Александр
          2019-11-12 15:13:58
          Спасибо, предельно понятно.