Статьи

Создание 5-звездочной рейтинговой системы с jQuery, AJAX и PHP

В этом уроке вы узнаете, как построить систему оценки с AJAX, PHP и jQuery. Голоса будут записываться и обновляться в режиме реального времени с помощью волшебства AJAX, и мы также используем возможности PHP, чтобы вам даже не понадобилась база данных!


Мы собираемся создать простую страницу, которая перечисляет два фильма и позволяет вам оценить их. Это означает, что нам нужны звезды, чтобы показать текущий рейтинг и разрешить голосование. Мы также хотим, чтобы область показывала общее количество поданных голосов, а текущий рейтинг – до одного десятичного знака.

Давайте посмотрим на HTML / CSS

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div class=’movie_choice’>
           Rate: Raiders of the Lost Ark
           <div id=”r1″ class=”rate_widget”>
               <div class=”star_1 ratings_stars”></div>
               <div class=”star_2 ratings_stars”></div>
               <div class=”star_3 ratings_stars”></div>
               <div class=”star_4 ratings_stars”></div>
               <div class=”star_5 ratings_stars”></div>
               <div class=”total_votes”>vote data</div>
           </div>
       </div>
        
       <div class=’movie_choice’>
           Rate: The Hunt for Red October
           <div id=”r2″ class=”rate_widget”>
               <div class=”star_1 ratings_stars”></div>
               <div class=”star_2 ratings_stars”></div>
               <div class=”star_3 ratings_stars”></div>
               <div class=”star_4 ratings_stars”></div>
               <div class=”star_5 ratings_stars”></div>
               <div class=”total_votes”>vote data</div>
           </div>
       </div>

Заметьте, что в этом HTML нет графики? Они будут добавлены с помощью CSS. Мы просто используем HTML для создания каркаса, из которого работает виджет. Теперь пришло время начать добавлять CSS.

1
.rate_widget { border: 1px solid #CCC;

Эта первая часть CSS выполняет несколько вещей:

  • Дает по умолчанию «пустой» старт каждой звездной локации
  • Устанавливает классы для залитых звезд и выделенных звезд
  • Определяет и стилирует контейнер звезд.

Вы можете использовать графику, представленную в загрузке, или сделать свою собственную. Для каждого из трех состояний должен быть рисунок: пустой, полный и выделенный.

Затем мы добавляем немного больше CSS, чтобы расположить поле общего количества голосов, и центрировать виджеты так, чтобы страница соответствовала графике в начале этого раздела.

01
02
03
04
05
06
07
08
09
10
11
12
.total_votes {
           background: #eaeaea;
           top: 58px;
           left: 0;
           padding: 5px;
           position: absolute;
       }
       .movie_choice {
           font: 10px verdana, sans-serif;
           margin: 0 auto 40px auto;
           width: 180px;
       }

На данный момент, у нас есть очень просто выглядящая группа пустых звезд, но они не очень много делают в этот момент. Это где jQuery приходит на помощь.

Наш первый шаг – добавить обработчики наведения и наведения мыши для звездочек. Нам нужно выделить звезду, над которой находится мышь, и все предыдущие звезды.

Мы используем преимущества мощных методов .prevAll () и .nextAll () jQuery, чтобы получить звезды, предшествующие и следующие за текущей звездой.

Код выше добавляет и удаляет классы, чтобы сделать звезды под мышью и перед «выделенными», а звезды после «не выделенных».

Это функция, которая проверяет, какие звезды должны быть в «полном» состоянии, и тесно связана со следующим шагом, где мы получаем удаленные данные с сервера.


Наши звезды подсвечиваются, когда вы наводите на них мышь, и это отличное начало. Но как насчет красных звезд, показывающих текущий голос? Чтобы достичь этого шага, нам нужно как получить информацию с сервера, так и написать JavaScript для обработки этих данных.

Этот блок кода – фактически весь JavaScript – входит в блок document.ready. Этот конкретный код выполняется сразу же. Он запрашивает сервер и получает некоторую информацию о каждом виджете голосования на странице.

Сначала мы устанавливаем объект out_data для хранения информации, которую мы отправляем на сервер. Наш PHP-скрипт ожидает увидеть «fetch» ​​при получении данных, поэтому мы включаем его здесь. Мы также включаем идентификатор виджета, который позволяет серверному сценарию знать, какие данные мы ищем. Когда функция обратного вызова срабатывает, она содержит объект JavaScript, который выглядит следующим образом:

Метод .data () – это немного волшебства jQuery, которое позволяет связывать произвольные данные с DOM
объект.

Если вы внимательно посмотрите на код, вы увидите, что мы берем этот объект (хранится в переменной INFO) и
делать что-то с помощью метода .data ().

Метод .data () – это немного волшебства jQuery, которое позволяет связывать произвольные данные с DOM
объект. В этом случае мы храним данные в div виджета. Это может быть доступно позже, как это:

После того, как данные были возвращены с сервера, они косвенно передаются set_votes ().

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

Строка 7: «avg» – это целое число, представляющее округленное среднее число голосов этого виджета. Потому что это
число 1-5, мы можем использовать его, чтобы найти правильную звезду в виджете, и повернуть его, и
предшествующие нашей «заполненной» графике. Обратите внимание на использование .andSelf () для включения звезды, которая
мы выбрали.

Строка 8: это очень похоже на строку семь, но мы удаляем заполненную графику из более поздних звезд. Эта
необходимо, если среднее значение для этого виджета уменьшилось с момента последнего голосования.

Строка 9: здесь мы обновляем серое поле под виджетом, которое показывает более точный рейтинг,
и позволяет посетителю узнать, сколько голосов было подано.


Последний шаг для пользовательского интерфейса – включить голосование. Мы собираемся добавить обработчик кликов для каждой звезды. Этот обработчик кликов будет отвечать за отправку данных голосования на сервер.

Вот обработчик кликов:

В этом блоке кода мы начинаем с создания некоторых переменных не только для ясности, но, в данном случае, чтобы они могли использоваться в обратном вызове .post. Помните, что обработчик кликов назначается звездам, поэтому нам также нужна вторая переменная, widget, для объекта, содержащего данные.

Сначала мы настраиваем наши исходящие данные, которые помещаем в объект clicked_data. Мы берем класс, который включает имя класса в формате star_ #, сообщающем нам, какой голос предоставляется, и готовимся отправить его на сервер вместе с идентификатором виджета.

Идентификатор виджета является краеугольным камнем, на котором основана эта система голосования. Это позволяет нам просматривать наши сохраненные данные и легко показывать эти данные посетителю.

Наконец, в строке мы отправляем эту информацию на сервер. Сервер добавит голосование к текущим итогам и отправит информацию обратно в браузер, содержащий обновленные данные. Значения, отображаемые виджетом, затем обновляются с помощью set_votes ().


Теперь, когда пользовательский интерфейс завершен, нам нужно создать скрипт на стороне сервера для хранения и извлечения данных голосования.

Мы собираемся создать очень простой класс в PHP под названием «Рейтинги» и использовать его для обработки запросов к серверу для нашей рейтинговой системы. Будут только два метода плюс вызов. Использование нашего класса будет выглядеть так:

1
2
3
4
5
# New Object
       $rating = new ratings($_POST[‘widget_id’]);
    
       # either return ratings, or process a vote
       isset($_POST[‘fetch’]) ?

Если вы вернетесь к четвертому разделу, вы увидите, что мы загружаем данные с установленной переменной ‘fetch’ – это то, что мы ищем здесь, в пятой строке. Если он не установлен, мы обрабатываем голосование.

Первое, на что мы пойдем, – начало класса и, более конкретно, конструктор.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
class ratings {
            
           private $data_file = ‘./ratings.data.txt’;
           private $widget_id;
           private $data = array();
               
       function __construct($wid) {
            
           $this->widget_id = $wid;
        
           $all = file_get_contents($this->data_file);
            
           if($all) {
               $this->data = unserialize($all);
           }
       }

serialize () и unserialize – отличный способ легко хранить
Структуры данных PHP на диске.

Здесь очень много всего происходит в нескольких строках, поэтому я расскажу о важных моментах.

Строка 3: это должен быть текстовый файл, который вы хотите использовать для хранения ваших данных. Мы не используем базу данных для этого проекта, хотя вы легко могли бы. Простой файл будет достаточно для наших нужд.

Строка 7: конструктор. Это вызывается, когда мы создаем наш объект, и сразу же сохраняет идентификатор виджета.

Строка 11: мы пытаемся загрузить текстовый файл. Если файл не существует, хорошо, но в некоторых системах вам нужно будет создать его заранее и дать ему необходимые разрешения для того, чтобы PHP мог читать и писать в него.

Строка 14: эта строка важна. Он берет данные из текстового файла (если он есть) и снимает его (). Этот файл содержит сложный массив PHP, который был преобразован в представление в виде простого текста с помощью serialize (), что позволяет нам сохранить его и позже прочитать в виде массива.


Этот метод вызывается либо самостоятельно, либо из метода voice (). Он находит данные для определенного идентификатора виджета и возвращает их на запрашивающую страницу в формате JSON.

1
public function get_ratings() { if($this->data[$this->widget_id]) { echo json_encode($this->data[$this->widget_id]);

Это только выглядит сложно – это на самом деле довольно просто. Первое, что мы делаем, это проверяем, имеет ли массив, хранящийся в $ this-> data, ключ, соответствующий нашему идентификатору виджета. Если это так, мы просто возвращаем эту информацию, потому что это данные виджета, которые запрашивала страница.

Нам не нужно ничего делать с этими данными, потому что они уже в форме массива. $ this-> data – это просто массив массивов. Мы кодируем нужный массив с помощью json_encode () и отправляем его обратно в браузер.

Если нет данных для запрашиваемого идентификатора виджета, мы создаем запись со всеми нулевыми значениями и отправляем ее обратно в браузер.

Далее нам нужно создать метод для обработки входящих голосов. Когда метод завершается, он должен вызвать get_ratings () для отправки обновленной информации обратно в веб-браузер.

1
2
3
4
public function vote() {
           # Get the value of the vote
           preg_match(‘/star_([1-5]{1})/’, $_POST[‘clicked_on’], $match);
           $vote = $match[1];

Первое, что мы делаем, это получаем значение голоса. Помните, что где-то в ‘clicked_on’ находится имя класса в формате star_ #. “star_4”, например. Чтобы получить это значение, мы используем регулярное выражение и записываем значение числа в $ match [1].

01
02
03
04
05
06
07
08
09
10
11
$ID = $this->widget_id;
# Update the record if it exists
if($this->data[$ID]) {
    $this->data[$ID][‘number_votes’] += 1;
    $this->data[$ID][‘total_points’] += $vote;
}
# Create a new one if it does not
else {
    $this->data[$ID][‘number_votes’] = 1;
    $this->data[$ID][‘total_points’] = $vote;
}

Здесь мы сохраняем $ this-> widget_id в $ ID для ясности – следующий код становится немного грубоватым без него.

Мы проверяем, существует ли информация для этого идентификатора, и, если так, добавляем голос к общему количеству голосов и добавляем баллы из полученных голосов. Это промежуточный итог всех голосов; так что если один человек дает пять звезд, а другой – три, то это всего восемь баллов.

Если запись не существует, мы создаем ее с одним голосом и только точками из входящего голосования.

1
2
3
4
5
6
    $this->data[$ID][‘dec_avg’] = round( $this->data[$ID][‘total_points’] / $this->data[$ID][‘number_votes’], 1 );
    $this->data[$ID][‘whole_avg’] = round( $this->data[$ID][‘dec_avg’] );
           
    file_put_contents($this->data_file, serialize($this->data));
    $this->get_ratings();
}

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

В четвертой строке мы храним измененную информацию обратно на диск после обработки с помощью serialize (). Как только данные благополучно сохранены, мы вызываем $ this-> get_ratings (), чтобы отправить новую, обновленную информацию в браузер.


Для простоты это не 100% полное решение. Чтобы расширить этот проект, мы должны сохранить cookie, чтобы люди могли голосовать только один раз или даже записать IP-адрес. Также возможно, что две пары первых голосов происходят одновременно, и может быть записана только одна. Это, однако, отличное начало, и оно более чем подходит для отслеживания голосов по нескольким элементам на вашем сайте. Мысли? Спасибо за прочтение!

Кстати, если вам нужна дополнительная помощь, попробуйте связаться с одним из поставщиков услуг PHP в Envato Studio. Вы можете исправлять ошибки, добавлять новые функции или разрабатывать целые приложения с нуля!

Поставщики услуг PHP на Envato Studio