Создаем обработчик рейтинга в виде звезд
По многочисленным просьбам трудящихся, сегодняшняя статья будет на тему того, как создать обработчик результатов голосования, которые отправляет на сервер рейтинг в виде звезд, о котором я писал здесь.
Что же, исправляю этот недочет.
Итак, первым делом давайте определимся со структурой базы данных. Можно конечно использовать уже существующую таблицу в Вашей базе данных, в которой хранятся все Ваши заметки, но я в этом примере создам новую таблицу, которая будет содержать всего 4 поля.
Это такие поля:
- id – id заметки;
- name – название заметки;
- vote – общая средняя оценка за статью;
- voters – количество проголосовавших.
Для того чтобы создать такую таблицу необходимо выполнить следующий SQL-запрос:
CREATE TABLE `articles` ( `id` int(11) NOT NULL auto_increment, `name` varchar(255) NOT NULL, `vote` float NOT NULL, `voters` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Если у Вас уже есть таблица, в которой хранятся заметки, то Вам необходимо добавить в неё 2 новых поля: vote и voters.
Теперь можно добавить тестовую информацию в базу данных:
INSERT INTO `articles` (`id`, `name`, `vote`, `voters`) VALUES (1, 'Тестовая заметка №1', 0, 0), (2, 'Тестовая заметка №2', 0, 0), (3, 'Тестовая заметка №3', 0, 0);
После того, как в базе данных есть несколько записей, их можно вывести на странице в виде списка. Кликнув по одной из них, пользователь попадает на страницу конкретной новости, где ему и будет предложено оценить статью.
Так как мы работаем с базой данных, то первым делом создадим самый простой класс для работы с базой данных. Для этого создадим файл db.class.php и поместим туда следующий php код:
class DB { private static $instance; private $MySQLi; private function __construct(array $dbOptions){ $this->MySQLi = @ new mysqli($dbOptions['db_host'],$dbOptions['db_user'], $dbOptions['db_pass'],$dbOptions['db_name'] ); if (mysqli_connect_errno()) { throw new Exception('Ошибка базы данных.'); } $this->MySQLi->set_charset("utf8"); } public static function init(array $dbOptions){ if(self::$instance instanceof self){ return false; } self::$instance = new self($dbOptions); } public static function getMySQLiObject(){ return self::$instance->MySQLi; } public static function query($q){ return self::$instance->MySQLi->query($q); } public static function esc($str){ return self::$instance->MySQLi->real_escape_string(htmlspecialchars($str)); } public static function insert_id($str){ return self::$instance->MySQLi->insert_id; } public static function affected_rows(){ return self::$instance->MySQLi->affected_rows; } }
Стоит сказать, что конструктор этого класса объявлен как private, таким образом, объект не может быть создан вне пределов класса, и инициализация возможна только из статического метода init(). Он берет массив с параметрами соединения с MySQL и создает экземпляр класса, который содержится в статической переменной self::$instance. Таким образом, обеспечивается существование единственного соединения с базой данных в конкретный момент времени.
Остальная часть класса, выполняет запросы к базе данных, на основе статического метода query().
Более подробно об объектно-ориентированном программировании в PHP можно почитать тут, тут и тут.
При желании Вы можете доработать этот класс, так как Вам это нужно!
Для того чтобы вывести список статей на страницу, необходимо создать эту страницу. Для этого создадим файлик articles.php и поместим в него самый простой html шаблон страницы:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Рейтинг заметок в виде звезд</title> <link href="styles/styles.css" rel="stylesheet" type="text/css" /> </head> <body> <div class="top_menu"> <div class="title"><h1><a href="/coding/156.html">Рейтинг заметок в виде звезд</a></h1></div> <div class="home"><a href="/"><<< На главную</a></div> </div> <div class="wrap"> <div class="border-wrap"> </div> </div> </body> </html>
Теперь в самое начало файла articles.php добавим следующий код:
<?php /* Конфигурация базы данных. Добавьте свои данные */ $dbOptions = array( 'db_host' => 'localhost', 'db_user' => '', 'db_pass' => '', 'db_name' => '' ); //Имя таблицы, в которой хранятся заметки $table_name = 'articles'; //Подключаем класс для работы с базой данных require "db.class.php"; // Соединение с базой данных DB::init($dbOptions); $page_id = (!empty($_GET['id']))? intval($_GET['id']): false; if(!$page_id){ //Выбираем 3 заметки из базы данных $result = DB::query('SELECT * FROM '.$table_name.' LIMIT 3'); //Здесь будет храниться список заметок $articles = array(); while($row = $result->fetch_assoc()){ $articles[] = $row; } } else{ //Выбираем заметку из базы данных по переданному id $result = DB::query('SELECT * FROM '.$table_name.' WHERE id='.$page_id.' LIMIT 1'); //Если такой заметки нет в базе данных //выводим 404 ошибку if(!$post = $result->fetch_assoc()){ header("HTTP/1.0 404 Not Found"); header("HTTP/1.1 404 Not Found"); header("Status: 404 Not Found"); die('Нет такой заметки'); } } ?>
Немного пояснений. Первым делом мы задаем основные параметры подключения к базе данных mysql и затем подключаем класс для работы с базой данных db.class.php, который мы создали выше. Затем соединяемся с базой данных использую статический метод init() класса DB.
После того, как подключение к базе данных установлено, проверяем передан ли GET параметр id. Если он передан, то делаем выборку из базы данных и получаем информацию о нужной статье, иначе выводим список статей.
Если в базе данных нет заметки с указанным id, то выводим 404 ошибку.
Теперь осталось на основе полученных данных сформировать нужную html-разметку.
<?php if(!empty($articles) && !isset($post)):?> <h1>Список заметок</h1> <?php foreach($articles as $article):?> <div class="border-wrap"> <h2><a href="vote.php?id=<?=$article['id'];?>"><?=$article['name'];?></a></h2> </div> <?php endforeach;?> <?php elseif(!empty($post)):?> <h1><?=$post['name'];?></h1> <div class="border-wrap"> <h2>Оцените эту статью:</h2> <div id="rating"> <input type="hidden" name="val" value="<?=$post['vote'];?>"/> <input type="hidden" name="votes" value="<?=$post['voters'];?>"/> <input type="hidden" name="vote-id" value="<?=$post['id'];?>"/> </div> </div> <div class="border-wrap"><a href="vote.php"><<< Вернуться к списку статей</a></div> <?php else:?> <div class="border-wrap"> <h2>В базе данных нет заметок!</h2> </div> <?php endif;?>
Здесь все просто. В начале проверяется если есть список статей, то в цикле проходимся по массиву $articles и формируем ссылки на страницы.
Если открыта конкретная страница новости, то выводим название этой статьи и формируем html-разметку для рейтинга в виде звезд.
<div id="rating"> <input type="hidden" name="val" value="<?=$post['vote'];?>"/> <input type="hidden" name="votes" value="<?=$post['voters'];?>"/> <input type="hidden" name="vote-id" value="<?=$post['id'];?>"/> </div>
О том, что обозначают все эти поля Вы можете прочитать здесь. Там же Вы найдете основные настройки плагина.
Если данных нет, то выводим сообщение о том, что в базе данных нет заметок.
После того, как html разметка сформирована, давайте вспомним, как же подключается рейтинг в виде звезд на сайт.
Первым делом необходимо подключить библиотеку jQuery и сам плагин jquery.rating.js на страницу, где будет размещен рейтинг. Это можно сделать так:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> <script type="text/javascript"> window.jQuery || document.write('<script type="text/javascript" src="js/jquery-1.6.2.min.js"><\/script>'); </script> <script type="text/javascript" src="js/jquery.rating-2.0.js"></script>
Данный код необходимо разместить между тегами <head></head> в нашем шаблоне.
О том, для чего необходимо подключать jQuery с репозитория Google можно почитать здесь.
Также для корректной работы плагина, необходимо подключить следующие стили:
<link href="styles/jquery.rating.css" rel="stylesheet" type="text/css" />
Что же идем дальше. После того, как html разметка рейтинга размещена в нужном месте на Вашем сайте, необходимо вызвать сам плагин рейтинга. Для этого используется следующий javascript-код:
$(function(){ $('#rating').rating({ fx: 'float', stars: 5, image: 'images/stars.png', loader: 'images/ajax-loader.gif', url: 'vote.php' }); })
Пару слов о том, что я здесь написал.
Если Вы обратили внимание, html разметка для рейтинга, которую Вы вставили на свой сайт имеет id равным id="rating". Зная этот id мы можем применить к этому блоку наш плагин, что мы и делаем. т. е. так:
$('#rating').rating();
Знак решетки означает, что элемент выбирается по id. Кто совсем не в теме, может прочитать статью «Что такое jQuery? Первое знакомство!»
Плагин имеет некоторые настройки, о которых я писал здесь. В данном примере я вызвал плагин со следующими параметрами:
- fx:'float' — это эффект при наведении, который означает, что звезды будут закрашиваться постепенно, следуя за указателем мыши
- stars: 5 - количество выводимых звезд в рейтинге
- image: 'images/stars.png' — здесь я указываю путь к изображению звезд
- loader: 'images/ajax-loader.gif' - здесь я указываю путь к изображению, которое будет выводится в тот момент, пока идет AJAX запрос на сервер
- url: 'rating.php' - адрес страницы, на которую будет отправлен AJAX запрос с результатом голосования
Итак, когда загрузится страница, плагин применится к нашему блоку с указанными настройками. Теперь когда пользователь кликнет по звезде, на страницу vote.php будет отправлен AJAX запрос, с результатом голосования.
Поэтому следующим шагом нам надо создать файл обработчик результатов голосования vote.php.
Результат голосования будет передан на сервер методом POST и будет хранится в переменной $_POST['score']. Также на сервер будет передан уникальный идентификатор замеки, который мы указали в скрытом поле:
<input type="hidden" name="vote-id" value="voteID"/>
Только вместо voteID Вы должны подставить свое значение уникального идентификатора, по которому будет идти выборка из базы данных. В нашем примере вместо voteID подставляется идентификатор статьи $post['id'].
Зная все эти данные, можно их обработать и записать в базу данных, тем самым обновив рейтинг заметки.
Давайте создадим обработчик результатов голосования vote.php и поместим туда следующий код:
<?php /* Конфигурация базы данных. Добавьте свои данные */ $dbOptions = array( 'db_host' => 'localhost', 'db_user' => '', 'db_pass' => '', 'db_name' => '' ); //Имя таблицы, в которой хранятся заметки $table_name = 'articles'; //Подключаем класс для работы с базой данных require "db.class.php"; // Соединение с базой данных DB::init($dbOptions); $use_cookie = true; //защита от накруток $expires = 3600*24*31; //время жизни кук в секундах (сейчас установлено 31 день) if(isset($_POST['score']) && isset($_POST['vote-id'])){ $page_id = intval($_POST['vote-id']); $cookie_name = 'page_'.$page_id; if($use_cookie && isset($_COOKIE[$cookie_name])){ $data['status'] = 'ERR'; $data['msg'] = 'Вы уже голосовали за эту заметку'; } else{ DB::query('UPDATE '.$table_name.' SET vote = (vote*voters + '.floatval($_POST['score']).')/(voters + 1), voters = voters + 1 WHERE id = '.$page_id); if(DB::affected_rows() == 1){ $data['status'] = 'OK'; $data['msg'] = 'Спасибо. Ваш голос учтен.'; if($use_cookie) setcookie($cookie_name,$page_id,time() + $expires); } else{ $data['status'] = 'ERR'; $data['msg'] = 'Произошла ошибка'; } } } else{ $data['status'] = 'ERR'; $data['msg'] = 'Вы не передали нужные данные!'; } echo json_encode($data); ?>
Здесь мы также первым делом указываем параметры подключения к базе данных, подключаем класс для работы с базой данных и устанавливаем соединение с базой данных, использую статический метод init() класса DB.
Далее идет опция $use_cookie - «Защита от накрутки» и время жизни кук. Если эта опция задана, то человек не сможет проголосовать 2 раза, пока время жизни кук не истечет или куки не будут удалены пользователем. Разумеется это очень примитивный метод защиты от накруток, но все же я решил показать, как это реализутеся.
После того, как все основные параметры заданы и соединение с базой данных установлено, идет проверка а были ли вообще переданы данные нашему обработчику.
Если данные переданы и пользователь еще не голосовал за эту статью, то обновляем данные в базе данных и включаем защиту от накрутки, установив куки с определенным временем жизни.
И в конце все данные преобразуются json объект и выводятся в браузер.
Надеюсь Вам будет полезна эта статья. Если есть какие-то вопросы, то отписуйтесь в комментариях ниже!
-
Комментарии (40)
- Сайт