Determining user location via IP and the creation of the hit counter

Hello dear Habracha! Creating my site, I added a hit counter with some service (something like qoo...), he worked with JS. And often updated. I couldn't see how much was actually on the website. Also I wanted to know from what IP addresses come to me, and which country this IP belongs. Not to create the bike decided to take a walk on the forums. Found a lot of information including about SxGeo. I liked this option because it can immediately know the country and the city. Since I'm just starting to learn PHP and such people are probably a lot, I decided to post this article. Not only the piece of code responsible for determining country and city, and fully working code. So, let's begin.



first we need to create a table in database where data will be entered on the visitors. I have all fields except id go with varchar 255 and comparison utf8_general_ci, id int 10 UNSIGNED attribute, and of course A/I. Now let's create a configuration file in which we write settings to connect to our database. Finally downloaded SxGeo.php and SxGeoCity.dat site sypexgeo.net links to both files: time and two.


In SxGeo.php 55 the line when you access the library you must replace the file name with SxGeo.dat on SxGeoCity.dat. All preparatory work is completed.


Create a file stats.php (the file name of your choice) and it established a connection to our database:


the
<?php
include_once ('config.php');
include_once ('SxGeo.php'); 
$mysqli = new mysqli($server, $user, $pswd, $db);
if ($mysqli- > connect_errno) {
printf("failed to connect: %s\n", $mysqli- > connect_error);
exit();}
$mysqli -> select_db($db) or die ("could not  open  $db");
if (!$mysqli- > set_charset("utf8")) {
printf("Error loading character set utf8: %s\n", $mysqli- > error);
exit();}

Now through the function getRealIpAddr() get the ip of the client:


the
public function getRealIpAddr() {
if (!empty($_SERVER['HTTP_CLIENT_IP'])) // Define the IP
{ $ip=$_SERVER['HTTP_CLIENT_IP']; }
elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
{ $ip=$_SERVER['HTTP_X_FORWARDED_FOR']; }
else { $ip=$_SERVER['REMOTE_ADDR']; }
return $ip;}

the Following check, not a bot if we went to visit:


the
if (strstr($_SERVER['HTTP_USER_AGENT'], 'YandexBot')) {$visitor='YandexBot';} //Identify search engine bots
elseif (strstr($_SERVER['HTTP_USER_AGENT'], 'Googlebot')) {$visitor='Googlebot';}
else { $visitor=$_SERVER['HTTP_USER_AGENT']; }

pass in $ip the value of the function getRealIpAddr().


the
$ip = getRealIpAddr();

Now create the object SxGeo and determine the city, country and region:


the
$SxGeo = new SxGeo('SxGeoCity.dat', SXGEO_BATCH | SXGEO_MEMORY);
$result = $SxGeo->getCityFull($ip); 

you Can use the var_export () to see what the data array you return, You may need something else besides what I offer. Go ahead. Choose from this array the values of the country, region and city. And to free up space deleting object SxGeo.


the
$city = $result["city"]["name_ru"];
$region = $result["region"]["name_ru"];
$country = $result["country"]["name_ru"];
unset($SxGeo);

Now determine the date, time and website page which came.


the
$date = date("H:i:s d.m.Y"); // define the date and time of the event
$host = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; // define page

Escapes special characters in a string for use in SQL expression and entered our data into the table.


the
$ip = $mysqli- > real_escape_string($ip);
$date = $mysqli- > real_escape_string($date);
$host = $mysqli- > real_escape_string($host);
$region = $mysqli- > real_escape_string($region);
$country = $mysqli- > real_escape_string($country);
$city = $mysqli->real_escape_string($city);
$visitor = $mysqli- > real_escape_string($visitor);
if ($query = $mysqli -> query("INSERT INTO `pre_visitors` (date, visitor, ip, country, region, city, host) VALUES ('".$date."', '".$visitor."', '".$ip."', '".$country."', '".$region."', '".$city."', '".$host."')")){
//printf("%d row inserted.\n", $mysqli->affected_rows);
}
else{
printf("Errorcode: %d\n", $mysqli->errno);
};

the Test can include the setup time, then I need not see. Now we need to get the values for our counter. The very form of the counter I took from the same site where the first counter in the DIVS inserted for the following values:


1. For those who came for the first time or with a different ip address:


//printf("%d row inserted.\n", $result->affected_rows); } $res1 = $result1 - > num_rows;

2. To the total number of hits:


the
if ($result = $mysqli -> query("SELECT MAX(id) AS id FROM `pre_visitors` ORDER BY id")){
//printf("%d row inserted.\n", $result->affected_rows);
}
$res = $result -> fetch_array();

and close the database connection:


the
$mysqli -> close();
?>

by the Way, do not forget to include our file stats.php to index.php. Now visualize our table. Create a file seestats.php and connect to our database:


the
<?php
include_once ('core/config_class.php');
$mysqli = new mysqli($server, $user, $pswd, $db) or die("cannot connect to MySQL.");
$mysqli -> select_db($db) or die("cannot connect to database.");
?>

Now some HTML to display it all on screen. I have added the choice of the number of rows returned.


the
<html>
<head>
<style type='text/css'>
td.zz {PADDING-LEFT: 3px; FONT-SIZE: 9pt; PADDING-TOP: 2px; FONT-FAMILY: Arial; }
</style>
</head>

<body>
<center>
<form action="seestats.php" method="get">
<select name="visualcount">
<option value="10" selected></option>
<option value="50">50</option>
<option value="100">100</option>
<option value="250">250</option>
<option value="500">500</option>
<option value="1000">1000</option>
</select>
<input type="button" value="Request">
</form>

Then processed our form requested in all fields on our table excluding bots and duplicate ip addresses, also requested the MAX id for the ending of our table.


the
<?php
$lastid = isset ($_GET['visualcount']) ? ($_GET['visualcount']) : '10';
if ($query = $mysqli->query("SELECT * FROM `pre_visitors`
WHERE (visitor NOT RLIKE 'bot') 
GROUP BY ip 
ORDER BY 'id' 
DESC LIMIT $lastid")){
//printf("%d rows retrieved.\n", $mysqli->affected_rows);
}
else{
printf("Errorcode: %d\n", $mysqli->errno);
};

if ($result = $mysqli -> query("SELECT MAX(id) AS id FROM `pre_visitors` ORDER BY id")){
//printf("%d rows retrieved.\n", $result->affected_rows);
}
$num_rows = $query -> num_rows;
$res = $result -> fetch_array();
?>

Create a table, styles, and sizes can use what you like:


the
<table width="680" cellspacing="1" cellpadding="1" border="0"
STYLE="table-layout:fixed">
<tr align = "center" bgcolor="#eeeeee">
<td class="zz" width="30"><b> n n/n</b></td>
<td class="zz" width="90"><b>Time and date</b></td>
<td class="zz" width="500"><b>Data about the visitor</b></td>
<td class="zz" width="100"><b>IP/proxy</b></td>
<td class="zz" width="100"><b>Country</b></td>
<td class="zz" width="100"><b>Region</b></td>
<td class="zz" width="100"><b>City</b></td>
<td class="zz" width="110"><b>Visited URLS</b></td>
</tr>

Now through the loop, we fill our table and close the database connection:


the
<?php
while($row = $query -> fetch_array()){
echo '<tr bgcolor="#eeeeee"><td class="zz">'.$row['id'].'</td>';
echo '<td class="zz">'.$row['date'].'</td>';
echo '<td class="zz">'.$row['visitor'].'</td>';
echo '<td class="zz">'.$row['ip'].'</td>';
echo '<td align = "center" class="zz">'.$row['country'].'</td>';
echo '<td align = "center" class="zz">'.$row['region'].'</td>';
echo '<td align = "center" class="zz">'.$row['city'].'</td>';
echo '<td class="zz">'.$row['host'].'</td></tr>';
}

echo '<tr bgcolor="#eeeeee"><td class="zz" colspan = "3" ><b>the Number of new visitors</b></td>';
echo '<td align = "center"><b>'.$num_rows.'</b></td>';
echo '<td class="zz" colspan = "3" ><b>the Total number of visits</b></td>';
echo '<td align = "center"><b>'.$res['id'].'</b></td></tr>';
echo '</table>';
echo '</center>';
echo '</body></html>';
$mysqli -> close();
?>

it is a Pity that you will get the IP of the proxy server, not a real client.
Thank you for your attention!

Article based on information from habrahabr.ru

Комментарии

Популярные сообщения из этого блога

March Habrameeting in Kiev

PostgreSQL load testing using JMeter, Yandex.Tank and Overload

Monitoring PostgreSQL with Zabbix