Генератор форм

Для веб-мастера

Реклама

Создаем обработчик рейтинга в виде звезд

Рейтинг:
Дата: 6 декабря 2011 Просмотры 35944 Комментарии 40

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

Что же, исправляю этот недочет.

Итак, первым делом давайте определимся со структурой базы данных. Можно конечно использовать уже существующую таблицу в Вашей базе данных, в которой хранятся все Ваши заметки, но я в этом примере создам новую таблицу, которая будет содержать всего 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 объект и выводятся в браузер.

Надеюсь Вам будет полезна эта статья. Если есть какие-то вопросы, то отписуйтесь в комментариях ниже!

Оцените эту статью:



Похожие статьи
Интересно почитать

    Получать новые материалы этого сайта на свой email адрес?

    Отправлять мне комментарии по эл. почте?

Простая CRM

Нашли ошибку в тексте

Система Orphus
https://biznesguide.ru/coding/162.html
4,02 из 5 на основе 830 оценок.