Для чего нужна функция лайков? В первую очередь, чтобы пользователи могли оценить Вашу запись, а также видеть, как её оценивают другие. Как сделать самостоятельно такой функционал - я расскажу в данном посте. Если Вам понравится данный пост - поставьте лайк! :)
Первым делом нам нужно создать таблицу в базе данных. Допустим, у нас сайт с базой данных MySQL. Если у Вас в проекте используется другая БД - перечень действий будет аналогичным, за исключением некоторых команд.
❶Создаём таблицу. Назовём её likes. Если Вы используете phpMyAdmin - находясь в корне всех таблиц, ниже кнопки "Создать таблицу" вводим имя likes, количество столбцов ставим 3, нажимаем "Вперёд".
Первому столбцу вводим имя - id, тип - INT, Индекс - PRIMARY (во всплывающем окне нажимаем ВПЕРЁД), ставим галочку A_I (auto increment).
Второму столбцу вводим имя - client_ip, тип - VARCHAR, длина - 15.
Третьему столбцу вводим имя - article_id, тип INT
Сравнение ставим utf8_general_ci, тип InnoDB.
Если Вы работаете с базой данных из консоли - находясь в режиме sql выполняем команду:
CREATE TABLE likes (id INT NOT NULL AUTO_INCREMENT, client_ip VARCHAR(15) NOT NULL, article_id INT NOT NULL, PRIMARY KEY (id)) ENGINE = InnoDB CHARSET=utf8 COLLATE utf8_general_ci;
Далее, для оптимизации таблицы сделаем уникальными связку "IP пользователя" - "ID поста". Это нужно для того, чтобы, если вдруг пользователь попытается проголосовать повторно за один и тот же пост, не происходило лишней записи в базу данных. Таким образом, с одного IP адреса проголосовать за один пост можно будет только один раз.
Выполняем SQL-запрос:
ALTER TABLE likes ADD UNIQUE INDEX (client_ip, article_id);
❷Далее создаём файл, назовём его like.php
В файле первым делом создаём подключение к базе данных:
<?php $link = mysqli_connect('имя_хоста', 'имя_пользователя', 'пароль', 'имя_БД'); $link->set_charset('utf8'); $link->query("SET NAMES utf8 COLLATE utf8_general_ci"); ?>
Если у Вас уже есть подключение к базе данных в отдельном файле, то просто подключаем этот файл через require_once().
Затем в файле like.php создаём переменные и делаем запрос к БД на вставку новых данных:
<?php $clientIp = $_POST['ip']; $article_id = $_POST['id']; $sql = "INSERT INTO likes (id, client_ip, article_id) VALUES (NULL, '$clientIp', '$article_id')"; $query = mysqli_query($link, $sql); ?>
❸Затем создаём PHP функцию для подсчёта лайков:
<?php function quantityLikes($postID) { // функция принимает ID поста global $link; $sql = "SELECT client_ip FROM likes WHERE article_id = '$postID' GROUP BY client_ip"; // выбираем IP из таблицы likes с уникальными значениями $query = mysqli_query($link, $sql); $likes = mysqli_fetch_all($query, 1); return $likes; } ?>
В результате вызова данной функции мы получим ассоциативный массив со значениями вида:
Array ( [0] => Array ( [client_ip] => 77.111.247.27 ) [1] => Array ( [client_ip] => 80.92.29.98 ) ... )
Поскольку мы передавали ID конкретного поста, то мы получаем список IP-адресов только для данного поста.
❹При загрузке страницы нам нужно определять, голосовал ли данный пользователь ранее за данный пост. Т.е. нам нужно определить его IP-адрес и проверить, есть ли он в массиве, полученном нами выше. К сожалению, стандартная функция PHP in_array() не подходит для проверки вхождения значений в ассоциативных массивах, поэтому мы будем использовать свою функцию:
<?php function is_in_array($array, $key, $key_value) { $within_array = false; foreach($array as $k=>$v) { if(is_array($v)) { $within_array = is_in_array($v, $key, $key_value); if($within_array == true) { break; } } else { if($v == $key_value && $k == $key) { $within_array = true; break; } } } return $within_array; } ?>
Функция возвратит нам true или false в зависимости от того, будет ли присутствовать IP-адрес пользователя в массиве адресов ранее голосовавших пользователей. Вызывать функцию будем со следующими параметрами:
is_in_array($likesArr, 'client_ip', $_SERVER['REMOTE_ADDR'])
❺Далее заходим в файл шаблона, формирующий наш пост и в верху файла пишем PHP-код:
<?php $likesArr = quantityLikes($post['id']); // в функцию quantityLikes мы передаём ID текущего поста. В моём блоге - это $post['id']. В Вашем это будет другое значение $likes = count($likesArr); // считаем лайки с помощью подсчёта общего значения количества элементов массива ?>
Далее в html-разметке вставляем:
<? if(!is_in_array($likesArr, 'client_ip', $_SERVER['REMOTE_ADDR'])): ?> <i title="Оцените пост"><img src="путь_на_иконку_для_новых_пользователей" class="icon_head" alt="" data-ip="<?=$_SERVER['REMOTE_ADDR']?>" data-post="<?=$post['id']?>"></i> <span id="countLikes"><?=$likes?></span> <? else : ?> <i title="Вы уже оценили данный пост"><img src="путь_на_иконку_для_уже_проголосовавших_ранее" class="icon_head noClick" alt=""></i> <span id="countLikes"><?=$likes?></span> <? endif; ?>
Таким образом, уже при загрузке страницы мы выводим разные иконки для новых или голосовавших ранее пользователей: для новых стандартно используется с пустым сердечком, для голосовавших - с заполненным. Также выводим в разных случаях разный title.
В data-параметрах для новых пользователей мы указали IP-адрес и ID данного поста. Эти параметры мы будем использовать в javascript-запросе к серверу при нажатии на иконку лайка.
❻Javascript:
<script> // событие загрузки страницы, не включая скрипты и картинки document.addEventListener("DOMContentLoaded", function() { var iconHead = document.querySelector('.icon_head'); if(iconHead) { // считаем количество текущих лайков и увеличиваем на 1 var countLikes = parseInt(document.getElementById('countLikes').textContent) +1; // по клику на иконку iconHead.addEventListener('click', function() { // увеличиваем цифру лайков на 1 document.getElementById('countLikes').textContent = countLikes; // меняем иконку (в моём случае - закрашенное сердечко) this.setAttribute('src', 'путь_на_иконку_для_уже_проголосовавших_ранее'); // добавляем css класс .noClick this.classList.add('noClick'); // записываем в переменную IP-пользователя из атрибута data-ip var clientIp = this.getAttribute('data-ip'); // записываем в переменную IP-пользователя из атрибута data-post var postId = this.getAttribute('data-post'); // создаём новый XMLHttpRequest для асинхронной передачи параметров на сервер var httpRequest = new XMLHttpRequest(); // указываем файл, на который идёт запрос var sendUrl = "/functions/like.php"; // в параметры записываем IP-клиента и ID статьи var sendParams = 'ip='+ clientIp +'&id=' + postId; httpRequest.open("POST", sendUrl, true); // устанавливаем заголовки httpRequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); // отправляем данные на сервер httpRequest.send(sendParams); }) } }); </script>
❼И напоследок, минимальный набор стилей:
.icon_head { height: 15px; width: 15px; cursor: pointer; } .noClick { pointer-events: none; /* делаем элемент некликабельным */ }
В итоге мы имеем удобный функционал:
- считающий лайки;
- с уникальными значениями в базе данных;
- с возможностью проголосовать 1 раз только с одного IP;
- не требующий никаких авторизаций через социальные сети или сервисы;
- не требующий зависимостей и сторонних библиотек.
Подписывайтесь на группу в ВКонтакте, вступайте в сообщество на Facebook, чтобы всегда быть в курсе актуальных выпусков
Web development blog!