О web-разработке
и даже немного больше...

Образец скрипта голосования (Like / Unlike) в связке AJAX/PHP/MySQL.

like-and-unlikeКак показывает практика, использование различных технологий в связке может дать неплохой результат, и в нашем случае этот факт не стал исключением. Сделаем скрипт голосования («За» / «Против») без перезагрузки страницы. Для реализации нам потребуется библиотека JQuery.

Для хранения наших данных используется MySQL, поэтому предварительно создаем таблицы в нашей базе:
1. Таблица posts – содержит данные постов. Необходимые поля в таблице id, like, unlike, name.
id – уникальный ключ поста;
like – сумма голосов «за»;
unlike – сумма голосов «против»;
name — имя поста;

posts-table

2. Таблица unique_likes – необходима для проверки уникальности голосов.
post_id – ключ поста (id в таблице posts).
ip_v4 – ip адрес от дублирования голосов.

unique_likes

Далее создаем файл, который будет содержать класс для подключения к серверу 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/

Опубликован: 07.02.2013 г.

См. также:

Делаем кнопки «Поделиться в соцсетях»
Стрелочные функции в JS
Мобильное меню для сайта на CSS
Опасность использования атрибута target="_blank"
Бесконечная анимация вращения на CSS
Анимация вращения при наведении курсора
Стилизация выделения номера телефона в мобильных браузерах
Эффекты кнопок для сайта

Комментарии

  1. Андрей пишет:

    А с одной таблицей нельзя сделать?

    1. htmaker пишет:

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

      1. vital пишет:

        А какая может быть проблема с большим количеством даных, если подразумевается, что один посетитель может поставить только один лайк или анлайк? Т.е. с каждым действием у тебя создается одинаковое количество записей в обеих таблицах. Поэтому целесообразней хранить IP в той же таблице, где и лайки, а дальше выбирать по ключам post_id и IP для проверки уникальности

        1. vital пишет:

          Прошу прощения, влез без дела.
          Я проглядел, что posts - это таблица постов, а не самих лайков. :) Просто я представил структуру, где лайки лежат отдельно для разных сущностей. Если данные о кол-ве лайков лежат непосредственно в таблице постов, то конечно структура со второй таблицей - верная.

  2. Абай пишет:

    Спасибо! А как можно сделать для конкретных статей?

    1. htmaker пишет:

      Для статей нужно добавить дополнительный параметр, скажем в таблице со статьями будет поле show_raiting, тип INT(1). Параметр будет отвечать показывать голосование в конкретной статье либо нет. На странице вывода статей делать проверку. Логически 1 - показ, 0 - нет.

  3. Денис пишет:

    Подскажите а можно ли будет сделать так: На стр подгружается инфа допустим название песни которое через некоторое время изменяется и нужно сделать так чтоб названию песни выдавался ид и если юзер нажал на мне нрав или не нрав название этой песни записалась в столбец с названием name в таблице posts и так же выдать ид именно этой песни в таблице unique_likes чтоб когда название песни изменилось и выдало новому названию другой ид можно было поставить нрав или не нрав. Если все это возможно подскажите как заранее большое спасибо!

  4. Миша пишет:

    Расширение mysql было признано устаревшим начиная с PHP 5.5.0 и полностью удалено в версии PHP 7. Похоже вам пора переходить на более современные средства работы с базой

  5. htmaker пишет:

    Первый релиз PHP7 версии был в 2014 году если я не ошибаюсь, статья была написана в 2013.

Добавить комментарий для Миша Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Комментарии
  • Загрузка...
Друзья сайта