Как показывает практика, использование различных технологий в связке может дать неплохой результат, и в нашем случае этот факт не стал исключением. Сделаем скрипт голосования («За» / «Против») без перезагрузки страницы. Для реализации нам потребуется библиотека JQuery.
Для хранения наших данных используется MySQL, поэтому предварительно создаем таблицы в нашей базе:
1. Таблица posts – содержит данные постов. Необходимые поля в таблице id, like, unlike, name.
id – уникальный ключ поста;
like – сумма голосов «за»;
unlike – сумма голосов «против»;
name — имя поста;
2. Таблица unique_likes – необходима для проверки уникальности голосов.
post_id – ключ поста (id в таблице posts).
ip_v4 – ip адрес от дублирования голосов.
Далее создаем файл, который будет содержать класс для подключения к серверу MySQL,
дадим ему имя mysql.php
Код:
<?php # Параметры MySQL define("DB_HOST","localhost"); # хост define("DB_NAME","test_like"); # имя базы define("DB_USER","user"); # имя пользователя define("DB_PASS","user_pass321"); # пароль # класс для работы MySQL class mySQL { public $DBConnect = false; function __construct(){ $this->connect(); } # подключение к базе private function connect(){ if (@$db = mysql_connect(DB_HOST, DB_USER, DB_PASS)){ if (mysql_select_db (DB_NAME,$db)){ mysql_query("SET NAMES 'UTF8'"); $this->DBConnect = $db; return true; } else { echo 'Не удалось открыть базу данных MySQL: '.mysql_error(); return false; } } else { echo 'Не удалось соединиться с базой данных MySQL: '.mysql_error(); return false; } } # выполнение SQL запроса # $resType - возвращаемый результат, может быть array/resource function query($sql,$resType='array'){ $res = mysql_query($sql,$this->DBConnect); if ($resType == 'resource'){ return $res; # ресурс } else { if ($res){ if (mysql_num_rows($res) > 0){ while($arr = mysql_fetch_assoc($res)){ $arRes[] = $arr; } return $arRes; # массив } else { return false; } } else { echo 'Ошибка выполнения запроса: '.$sql.mysql_error(); return false; } } } } ?>
Создаем страницу, которая будет показываться пользователю, назовём её index.php
Код:
<?php require_once('mysql.php'); # библиотека для работы с MySQL $dbObj = new MySQL(); # при успешном запросе, результат будет в виде массива $arPostsList = $dbObj->query("SELECT * FROM posts"); ?> <html> <head> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script> </head> <body> <?if (is_array($arPostsList) && count($arPostsList) > 0){?> <script type="text/javascript"> function doAction(id,type){ $.post('doAjax.php', {id:id, type:type}, function(data){ if(isNaN(parseFloat(data))){ alert(data); }else{ $('#'+id+'_'+type+'s').text(data); } }); } </script> <?foreach ($arPostsList as $arPost){?> <div style="border:1px solid #778899;"> <h2><?=$arPost['name']?></h2> <a href="javascript:;" onclick="doAction('<?=$arPost['id'];?>','like');">Нравится (<span id="<?=$arPost['id'];?>_likes"><?=$arPost['like'];?></span>)</a> <a href="javascript:;" onclick="doAction('<?=$arPost['id'];?>','unlike');">Не нравится (<span id="<?=$arPost['id'];?>_unlikes"><?=$arPost['unlike'];?></span>)</a> </div> <?} }?> </body> </html>
Создаем обработчик, который собственно и будет выполнять всю основную работу, назовём файл doAJAX.php.
Код:
<?php require_once('mysql.php'); # библиотека для работы с MySQL $dbObj = new MySQL(); if(isset($_POST['id']) && isset($_POST['type'])){ $arULike = $dbObj->query(' SELECT * FROM unique_likes WHERE post_id="'.(int)$_POST['id'].'" AND ip_v4="'.$_SERVER['REMOTE_ADDR'].'"'); if(!$arULike){ if ($_POST['type']=='like'){ $dbObj->query(' UPDATE posts SET `like`=`like`+1 WHERE id="'.(int)$_POST['id'].'"','resource'); $arSNum = $dbObj->query(' SELECT `like` FROM posts WHERE id="'.(int)$_POST['id'].'" LIMIT 1'); echo $arSNum[0]['like']; } elseif($_POST['type']=='unlike'){ $dbObj->query(' UPDATE posts SET `unlike`=`unlike`+1 WHERE id="'.(int)$_POST['id'].'"','resource'); $arSNum = $dbObj->query(' SELECT `unlike` FROM posts WHERE id="'.(int)$_POST['id'].'" LIMIT 1'); echo $arSNum[0]['unlike']; } $dbObj->query('INSERT INTO unique_likes (`post_id`,`ip_v4`) VALUES ("'.(int)$_POST['id'].'","'.$_SERVER['REMOTE_ADDR'].'")','resource'); } else { echo 'Вы уже проголосовали'; } } ?>
Итак, в итоге у нас должны получиться следующие файлы:
mysql.php – файл подключения к БД MySQL.
doAJAX.php – обработчик AJAX запросов.
index.php – страница, показываемая пользователю.
Исходники в архиве:
https://href.kz/example/like-unlike/files.rar
Рабочий пример:
https://href.kz/example/like-unlike/
А с одной таблицей нельзя сделать?
Думаю можно, однако хранить такие вещи в разных таблицах более предпочтительнее с точки зрения удобства работы с данными, а так же производительности при большом кол-ве записей в таблицах.
А какая может быть проблема с большим количеством даных, если подразумевается, что один посетитель может поставить только один лайк или анлайк? Т.е. с каждым действием у тебя создается одинаковое количество записей в обеих таблицах. Поэтому целесообразней хранить IP в той же таблице, где и лайки, а дальше выбирать по ключам post_id и IP для проверки уникальности
Прошу прощения, влез без дела.
Я проглядел, что posts - это таблица постов, а не самих лайков. :) Просто я представил структуру, где лайки лежат отдельно для разных сущностей. Если данные о кол-ве лайков лежат непосредственно в таблице постов, то конечно структура со второй таблицей - верная.
Спасибо! А как можно сделать для конкретных статей?
Для статей нужно добавить дополнительный параметр, скажем в таблице со статьями будет поле show_raiting, тип INT(1). Параметр будет отвечать показывать голосование в конкретной статье либо нет. На странице вывода статей делать проверку. Логически 1 - показ, 0 - нет.
Подскажите а можно ли будет сделать так: На стр подгружается инфа допустим название песни которое через некоторое время изменяется и нужно сделать так чтоб названию песни выдавался ид и если юзер нажал на мне нрав или не нрав название этой песни записалась в столбец с названием name в таблице posts и так же выдать ид именно этой песни в таблице unique_likes чтоб когда название песни изменилось и выдало новому названию другой ид можно было поставить нрав или не нрав. Если все это возможно подскажите как заранее большое спасибо!
Расширение mysql было признано устаревшим начиная с PHP 5.5.0 и полностью удалено в версии PHP 7. Похоже вам пора переходить на более современные средства работы с базой
Первый релиз PHP7 версии был в 2014 году если я не ошибаюсь, статья была написана в 2013.