Create a Hit Counter with Redis® Hash Map and PHP on Ubuntu 20.04
Introduction
A Redis® hash map is a data type that stores key-pair values as an associative array. By using Redis® hash tables, you can benefit from fast lookups and flexible keys. These advantages make Redis® the perfect NoSQL database for creating a hit counter for your applications or websites. The hit counter stores the number of visits made to a web resource in your server. Because Redis® is an in-memory database, it is several times faster than even the fastest SSD in the market today and is suitable for this job.
You'll set up a web counter on Ubuntu 20.04 using a Redis® hash map in this guide. When a PHP web resource on your server receives a visit, Redis® will increment a counter based on each visitor's IP address. You'll also create a human-readable report to display hit counts for each user making visits to the resource on your server.
Prerequisites
This guide requires:
- An Ubuntu 20.04 server.
- A sudo user.
- A LAMP Stack. You may skip the installing MySQL server, which is not required for this guide.
- A Redis® Server.
Install php-redis
Extension
To begin, SSH to your server and install the php-redis
library. This is an extension that allows you to use the Redis® functionalities within the PHP code.
$ sudo apt update
$ sudo apt install -y php-redis
Restart Apache to load the php-redis
module.
$ sudo systemctl restart apache2
Create a Sample Web Resource File
With the php-redis
library in place, you'll create a sample_resource.php
file. In this file, you'll determine the visitor's IP address and log the number of visits they've made to the server.
Open the file /var/www/html/sample_resource.php
using nano.
$ sudo nano /var/www/html/sample_resource.php
Add the information below into the file.
<?php
try {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$client_ip_address = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$client_ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$client_ip_address = $_SERVER['REMOTE_ADDR'];
}
if ($redis->hExists('visitor_stats', $client_ip_address)) {
$my_array = $redis->hMget("visitor_stats", array($client_ip_address));
$total_counts = $my_array[$client_ip_address] + 1;
} else {
$total_counts = 1;
}
$redis->hSet('visitor_stats', $client_ip_address, $total_counts);
echo "Welcome, your IP is " . $client_ip_address . ". You've visited this page ". $total_counts . " times\n";
} catch (Exception $e) {
echo $e->getMessage();
}
?>
Once you're through with editing, save the file by pressing Ctrl + X, then Y and Enter.
The sample_resource.php
explained:
The below code connects to your local Redis® server on port
6379
.$redis = new Redis(); $redis->connect('127.0.0.1', 6379);
You've used the code snippet below to retrieve the client's IP address.
if (!empty($_SERVER['HTTP_CLIENT_IP'])) { $client_ip_address = $_SERVER['HTTP_CLIENT_IP']; } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $client_ip_address = $_SERVER['HTTP_X_FORWARDED_FOR']; } else { $client_ip_address = $_SERVER['REMOTE_ADDR']; }
In the below code, you're using the Redis®
hMget
method to check if the hash tablevisitor_stats
contains a key identified by the client IP address variable ($client_ip_address
). If the key exists, you're retrieving the total count of visits using the statement$total_counts = $my_array[$client_ip_address] + 1;
. Otherwise, in case this is the first time a client is making a visit, you're initializing the counts to1
using the PHP code$total_counts = 1;
if ($redis->hExists('visitor_stats', $client_ip_address)) { $my_array = $redis->hMget("visitor_stats", array($client_ip_address)); $total_counts = $my_array[$client_ip_address] + 1; } else { $total_counts = 1; }
Finally, you're setting a new value for the client visiting the web resource using the Redis®
hSet
function. You've also used the PHPecho
command to display the number of visits a client has made to the web resource.$redis->hSet('visitor_stats', $client_ip_address, $total_counts); echo "Welcome, your IP is " . $client_ip_address . ". You've visited this page ". $total_counts . " times\n";
Once you've coded and closed the /var/www/html/sample_resource.php
, you'll test it in the next step to see if it is working as expected.
Testing the Resource File
Use Linux curl
command to request the sample_resource.php
resource file that you've created.
$ curl localhost/sample_resource.php
You should see the output below showing the number of times you've visited the resource because this is the first time. The total counts should be 1
.
Welcome, your IP is 127.0.0.1. You've visited this page 1 times
Display Human Readable Stats
Create a detailed report file that shows the total visits made and group them by the IP addresses. Open /var/www/html/stats.php
using nano.
$ sudo nano /var/www/html/stats.php
Then, add the information below into the file.
<?php
try {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$stats = $redis->HGETALL("visitor_stats");
echo "\nIP ADDRESS VISITS\n";
echo "--------- ------\n";
foreach ($stats as $key => $value) {
echo $key . "\t" . $value . "\n";
}
} catch (Exception $e) {
echo $e->getMessage();
}
?>
In the above file, you are using the Redis® HGETALL
function to create an array of IP addresses and their total visits registered to the Redis® server. Then, you're using the PHP ...foreach(...){...}...
statement to loop through the list and echo
out each visitor's total visits in a new line.
After you've finished editing the file, save and close it. Next, run a curl
command against the resource to get the report.
$ curl localhost/stats.php
You should see an output like the one shown below. Please note, this output may be different depending on the number of visits that you've made to the localhost/sample_resource.php
page.
IP ADDRESS VISITS
--------- ------
127.0.0.1 1
IP ADDRESS 2 1
IP ADDRESS 3 1
The output above confirms that the Redis® hit counter is working as expected.
Conclusion
In this guide, you've used the Redis® hash map to create a hit counter with PHP on Ubuntu 20.04. You may extend the code in this tutorial to suit your needs when implementing a web counter depending on your use-case.