How to write a function like for the site


22-10-2018
Денис Л.
Разное
How to write a function like for the site

What is the function of likes for? First of all, so that users can evaluate your record, as well as see how others rate it. How to make yourself such a functional - I will tell in this post. If you like this post - like it! :)

First we need to create a table in the database. Suppose we have a website with a MySQL database. If you use another database in the project - the list of actions will be the same, except for some commands.

Create a table. Let's call her likes. If you use phpMyAdmin - being in the root of all tables, below the button "Create table" enter the name likes, the number of columns set 3, push "Forward".

Enter the name of the first column - id, type of - INT, Index - PRIMARY (in the pop-up window, press FORWARD), put a tick A_I (auto increment).

Enter the name of the second column - client_ip, type of - VARCHAR, length - 15.

Enter the name of the third column - article_id, type of INT

Comparison set utf8_general_ci, type of InnoDB.


If you are working with a database from the console - being in sql mode, we execute the command:

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;

Further, to optimize the table, we will make a unique bunch "User IP" - "Post ID". This is necessary so that if the user suddenly tries to vote again for the same post, there will not be an extra record in the database. Thus, from one IP address you can vote for one post only once.

Execute SQL query:

ALTER TABLE likes ADD UNIQUE INDEX (client_ip, article_id);

Next, create a file, call it like.php

First of all, create a database connection in the file.:

<?php
$link = mysqli_connect('hostname', 'user_name', 'password', 'database_name');
$link->set_charset('utf8');
$link->query("SET NAMES utf8 COLLATE utf8_general_ci"); 
?>

If you already have a connection to the database in a separate file, then simply connect this file via require_once().

Then in the file like.php we create variables and make a request to the database to insert new data:

<?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) { // function accepts post ID
    global $link;
    $sql = "SELECT client_ip FROM likes WHERE article_id = '$postID' GROUP BY client_ip"; // choose IP from the likes table with unique values
    $query = mysqli_query($link, $sql);
    $likes = mysqli_fetch_all($query, 1);
    return $likes;
}
?>

As a result of calling this function, we get an associative array with values like:

Array
(
    [0] => Array
        (
            [client_ip] => 77.111.247.27
        )

    [1] => Array
        (
            [client_ip] => 80.92.29.98
        )
    ...
)

Since we passed the ID of a specific post, we get a list of IP addresses only for this post.

When loading the page, we need to determine whether this user has previously voted for this post. Those. we need to determine its IP address and check if it is in the array we got above. Unfortunately, the standard PHP function in_array() not suitable for checking the occurrence of values in associative arrays, so we will use our function:

<?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 or false depending on whether the user's IP address is present in the array of addresses of previously voted users. We will call the function with the following parameters:

is_in_array($likesArr, 'client_ip', $_SERVER['REMOTE_ADDR'])

Next, go to the template file that forms our post and at the top of the file write the PHP code:

<?php
$likesArr = quantityLikes($post['id']); // in the quantityLikes function, we pass the ID of the current post. In my blog it is $post['id']. In your it will be a different meaning.
$likes = count($likesArr); // counting likes by counting the total number of elements in an array
?>

Next, insert the html markup:

<? if(!is_in_array($likesArr, 'client_ip', $_SERVER['REMOTE_ADDR'])): ?>
<i title="Rate post"><img src="path_to_icon_for_new_user_user" class="icon_head" alt="" data-ip="<?=$_SERVER['REMOTE_ADDR']?>" data-post="<?=$post['id']?>"></i> <span id="countLikes"><?=$likes?></span>
<? else : ?>
<i title="You have already rated this post"><img src="path_ on_on_on_for_to_utilized_starting_ in advance" class="icon_head noClick" alt=""></i> <span id="countLikes"><?=$likes?></span>
<? endif; ?>

Thus, already when the page is loaded, we display different icons for new or previously voted users: for new ones it is standardly used with an empty heart, for those who have voted - with a full one. Also output in different cases different title.

In the data parameters for new users, we specified the IP address and ID of this post. We will use these parameters in the javascript request to the server when clicking on the like icon.

Javascript:

<script>
// page load event, not including scripts and images
document.addEventListener("DOMContentLoaded", function() {
    var iconHead = document.querySelector('.icon_head');
    if(iconHead) {
        // count the number of current likes and increase by 1
        var countLikes = parseInt(document.getElementById('countLikes').textContent) +1;
        // by clicking on the icon
        iconHead.addEventListener('click', function() {
            // increase the number of likes by 1
            document.getElementById('countLikes').textContent = countLikes;
            // change icon (in my case - painted heart)
            this.setAttribute('src', 'path_ on_on_on_for_to_utilized_starting_ in advance');
            // add css class .noClick
            this.classList.add('noClick');
            // write to the variable IP-user from the data-ip attribute
            var clientIp = this.getAttribute('data-ip');
            // write to the variable IP-user from the data-post attribute
            var postId = this.getAttribute('data-post');
            // create new XMLHttpRequest for asynchronous transfer of parameters to the server
            var httpRequest = new XMLHttpRequest();
            // we specify the file to which the request goes
            var sendUrl = "/functions/like.php";
            // write IP client and article ID to parameters
            var sendParams = 'ip='+ clientIp +'&id=' + postId
            httpRequest.open("POST", sendUrl, true);
            // set headers
            httpRequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
            // send data to the server
            httpRequest.send(sendParams);
        })
    }
});
</script>

And finally, the minimum set of styles:

.icon_head {
    height: 15px;
    width: 15px;
    cursor: pointer;
}
.noClick {
    pointer-events: none; /* make the item non-clickable */
}

As a result, we have a convenient functionality.:

  • counting likes;
  • with unique values in the database;
  • with the ability to vote once with only one IP;
  • not requiring any authorization via social networks or services;
  • no dependencies and third-party libraries.