PHP

Сколько посетителей в данный момент находится на сайте

В этом уроке мы сделаем полезный виджет, который будет отслеживать сколько посетителей в данный момент находится на сайте.

Более он также будет способен определять страну, возраст, и заработную плату (шутка) посетителя. Страна будет определяться с помощью бесплатного сервиса http://www.hostip.info/. Если быть более точным, то с помощью АПИ сервиса.

Шаг 1 - XHTML

Как всегда мы начинаем с фундамента. Кода совсем немного. Основная работа будет вестись над серверной частью. Наш виджет будет состоять из красивой кнопки с отображением количества человек, при нажатии на которую всплывает более подробная таблица с флагами стран.

demo.html
<div class="onlineWidget">

<div class="panel">

	<!-- Спарсено с помощью AJAX: -->

	<div class="geoRow">
	<div class="flag"><img src="who-is-online/img/famfamfam-countryflags/us.gif" width="16" height="11"></div>
	<div class="country" title="UNITED STATES">UNITED STATES</div>
	<div class="people">2</div>
	</div>

	<div class="geoRow">
	<div class="flag"><img src="who-is-online/img/famfamfam-countryflags/uk.gif" width="16" height="11"></div>
	<div class="country" title="UNITED KINGDOM">UNITED KINGDOM</div>
	<div class="people">1</div>
	</div>

</div>

<div class="count">8</div>
<div class="label">online</div>
<div class="arrow"></div>
</div>

Как Вы можете заметить из разметки выше, главный контейнер - "onlineWidget" содержит выезжающую панель (div с классом "panel"), общее количество посетителей онлайн (div "count"), ярлык "online" и зеленую стрелку справа.

div выезжающей панели наполняется динамически с помощью AJAX. Содержание этой панели по умолчанию - вращающийся файл gif, который вскоре заменяется гео информацией после обработки AJAX запроса. К этому мы еще вернемся.

Шаг 2 - База данных

Вся информация виджета хранится в таблице tz_who_is_online. Она состоит из шести полей (или колонок). Первое - ID (первичный ключ + автодобавление), второе - IP (сохраняет IP адрес, который преобразован в целое число с помощью функции ip2long).

Далее следуют три поля, которые берутся из Hostip API - Country, CountryCode и City. Виджет на данный момент не использует поле CITY (город), но на случай если кто-то захочет доработать его - оно пригодится. Последнее поле - DT - временной штамп, который обновляется при каждой загрузки страницы и позволяет определить кто онлайн (пользователи, которые не обновляют страницу на протяжении 10 минут скорее всего уже покинули сайт).

Шаг 3 - CSS

Виджет практически не использует картинок. Давайте взглянем на стили:

who-is-online/styles.css - часть 1
.onlineWidget,.panel{

	background-color:#F9F9F9;
	border:2px solid #FFFFFF;
	height:25px;
	padding:4px 8px;
	position:relative;
	width:130px;

	cursor:pointer;

	/* CSS3 правила для закругленных углов и теней: */

	-moz-border-radius:6px;
	-webkit-border-radius:6px;
	border-radius:6px;

	-moz-box-shadow:0 0 3px #CCCCCC;
	-webkit-box-shadow:0 0 3px #CCCCCC;
	box-shadow:0 0 3px #CCCCCC;

	text-shadow:0 2px 0 white;
}

.onlineWidget:hover{
	background-color:#fcfcfc;
}

.onlineWidget:hover .arrow{
	/* Меняем фоновое изображение для зеленой стрелки при наведении: */
	background-position:bottom center;
}

.count{
	/* Общее количество человек онлайн - div */

	color:#777777;
	float:left;
	font-size:26px;
	font-weight:bold;
	margin-top:-3px;
	text-align:center;
	width:30px;
}

.label{
	/* Ярлык - online */

	float:left;
	font-size:10px;
	padding:7px 0 0 7px;
	text-transform:uppercase;
}

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

who-is-online/styles.css - часть 2
.arrow{
	/* Зеленая стрелочка справа */

	background:url(img/arrow.png) no-repeat top center;
	position:absolute;
	right:6px;

	width:25px;
	height:25px;
}

.panel{
	/* Выезжающая панель */

	position:absolute;
	cursor:default;

	bottom:50px;
	left:0;
	height:auto;
	display:none;
	margin:-2px;
	z-index:1000;
}

.preloader{
	/* Вращающийся прелоадер gif */
	display:block;
	margin:10px auto;
}

.geoRow{
	/* div, который содержит каждую страну */

	height:16px;
	overflow:hidden;
	padding:2px 0;
}

.flag{
	float:left;
	margin:0 4px;
}

.country, .people{
	float:left;
	font-size:10px;
	padding:2px;
}

.country{
	width:85px;
	overflow:hidden;
}

.people{
	font-weight:bold;
}

Во второй части стилей мы описываем то, как должна выглядеть информации после получения ее от AJAX запросов.

Шаг 4 - PHP

Именно здесь происходит вся магия. PHP должен сохранять базу данных посетителей онлайн постоянно обновленной, а также извлекать гео информацию от Hostip API. В дальнейшем это кешируется для дальнейшего использования в виде "куки" на компьютере пользователя.

who-is-online/online.php
require "connect.php";
require "functions.php";

// Мы не хотим, чтобы поисковые боты искажали статистику:
if(is_bot()) die();

$stringIp = $_SERVER['REMOTE_ADDR'];
$intIp = ip2long($stringIp);

// Проверяем отмечен ли посетитель как "онлайн":
$inDB = mysql_query("SELECT 1 FROM tz_who_is_online WHERE ip=".$intIp);

if(!mysql_num_rows($inDB))
{
	// Этого пользователя нет в БД, значит мы должны
	// извлечь всю гео информацию и вставить в таблицу:

	if($_COOKIE['geoData'])
	{
		// "geoData" cookie установлена ранее скриптом, и мы будем ей пользоваться

		list($city,$countryName,$countryAbbrev) = explode('|',mysql_real_escape_string(strip_tags($_COOKIE['geoData'])));
	}
	else
	{
		// Делаем API запрос Hostip:

		$xml = file_get_contents('http://api.hostip.info/?ip='.$stringIp);

		$city = get_tag('gml:name',$xml);
		$city = $city[1];

		$countryName = get_tag('countryName',$xml);
		$countryName = $countryName[0];

		$countryAbbrev = get_tag('countryAbbrev',$xml);
		$countryAbbrev = $countryAbbrev[0];

		// делаем cookie wс информацией, который будет действителен в течении месяца:
		setcookie('geoData',$city.'|'.$countryName.'|'.$countryAbbrev, time()+60*60*24*30);
	}

	$countryName = str_replace('(Unknown Country?)','UNKNOWN',$countryName);

	mysql_query("	INSERT INTO tz_who_is_online (ip,city,country,countrycode)
					VALUES(".$intIp.",'".$city."','".$countryName."', '".$countryAbbrev."')");
}
else
{
	// Если пользователь онлайн, просто внести изменения в значение поля dt:
	mysql_query("UPDATE tz_who_is_online SET dt=NOW() WHERE ip=".$intIp);
}

// убираем записи, которые не обновлялись в течении 10 минут:
mysql_query("DELETE FROM tz_who_is_online WHERE dt<SUBTIME(NOW(),'0 0:10:0')");

// Подсчитываем всех посетителей онлайн:
list($totalOnline) = mysql_fetch_array(mysql_query("SELECT COUNT(*) FROM tz_who_is_online"));

// Выводим число как простой текст:
echo $totalOnline;

Этот PHP скрипт вызывается с помощью jQuery для вставки текущего количества человек онлайн в соответствующее место. "За кулисами" этот скрипт записывает IP адрес пользователя в базу данных и уточняет всю необходимую гео информацию.

Это лучшая стратегия организации серверной части, так как мы запросы к АПИ распределяются каждому пользователя при их первом посещении.

Вы можете сделать запрос на Hostip API обращаясь по УРЛ типа http://api.hostip.info/?ip=128.128.128.128. И получите валидный XML ответ, который будет содержать разного рода инфомрацию, включая страну, название города связанного с этим IP, аббревиатуру страны, а также абсолютные координаты. Мы извлекаем эту информацию с помощью функции PHP file_get_contents() и выбираем необходимую нам информацию.

who-is-online/geodata.php
require "connect.php";
require "functions.php";

// Не хотим, чтобы боты искажали статистику:
if(is_bot()) die();

// Выбираем топ 15 стран с большинством посетителей:
$result = mysql_query("	SELECT countryCode,country, COUNT(*) AS total
						FROM tz_who_is_online
						GROUP BY countryCode
						ORDER BY total DESC
						LIMIT 15");

while($row=mysql_fetch_assoc($result))
{
	echo '
	<div class="geoRow">
		<div class="flag"><img src="who-is-online/img/famfamfam-countryflags/'.strtolower($row['countryCode']).'.gif" width="16" height="11" /></div>
		<div class="country" title="'.htmlspecialchars($row['country']).'">'.$row['country'].'</div>
		<div class="people">'.$row['total'].'</div>
	</div>
	';
}

Geodata.php прочитывается с помощью jQuery для публикации информации в выезжающую панель. Файл делает запрос в БД с запросом GROUP BY, который группирует пользователей по стране и выстраивает их по количеству посетителей (чем больше с одной страны - тем выше в списке).

Для иконок флагов используется набор от famfamfam. Большой плюс Hostip API в том, что также он выдает аббревиатуры страны в формате 2-х букв, что также поддерживается и в иконках. Таким образом скрипту очень просто найти необходимый флаг при его поиске в папке.

Шаг 5 - jQuery

JavaScript управляет AJAX запросами и выездом панели. Давайте взглянем на код:
$(document).ready(function(){
	// Функция выполняется только после загрузки документа

	// Кешируем jQuery селекторы:
	var count = $('.onlineWidget .count');
	var panel = $('.onlineWidget .panel');
	var timeout;

	// Загружаем количество пользователей онлайн в специальный div с помощью метода AJAX:
	count.load('who-is-online/online.php');

	$('.onlineWidget').hover(
		function(){
			// задаем пользовательское событие 'open' для выезжающей панели:

			clearTimeout(timeout);
			timeout = setTimeout(function(){panel.trigger('open');},500);
		},
		function(){
			// пользовательское событие 'close':

			clearTimeout(timeout);
			timeout = setTimeout(function(){panel.trigger('close');},500);
		}
	);

	var loaded=false;	// предотвращает множественное количество запросов AJAX для geodata.php;

	// Привет! Вызываем функции к пользовательским событиям:

	panel.bind('open',function(){
		panel.slideDown(function(){
			if(!loaded)
			{
				// Загружаем страны и флаги
				// после открытия выезжающей панели:

				panel.load('who-is-online/geodata.php');
				loaded=true;
			}
		});
	}).bind('close',function(){
		panel.slideUp();
	});

});

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

Вот и все готово! Думаю, подобная фишка пригодится многим!

Настройка на своем сервере

В исходниках находится SQL код, который необходимо выполнить после создания БД. Он создаст таблицу, которая используется виджетом. После этого Вам необходимо загрузить все файлы на Ваш сервер и подключить widget.js в шапку документа (вместе с jQuery фреймворком). После этого не забудьте внести Ваши данные для соединения с БД в файле connect.php. И в самом конце добавьте разметку из файла demo.html в необходимом месте Вашего документа.
Добавлено: 21 Августа 2013 11:28:30 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...