Кто OnLine? 2

Среда, 3 августа 2011 г.
Рубрика: PHP программирование -> Готовые решения
Метки: | | |
Просмотров: 799
Подписаться на комментарии по RSS
Сегодня мы с Вами создадим более мощную и функциональную систему Кто OnLine.

В прошлом уроке мы с Вами научились просто выводить кол-во уникальных сессий на сайте - то есть кол-во каких-то уникальных ip-адресов - посетителей.

Но мы не определяли кто это!

На сайте могут присутствовать разные категории посетителей, типа - гости, пользователи и администраторы.

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

И так, что же нового будет в нашей системе Кто Online?

1) Будет выводиться кол-во гостей

2) Будет выводиться кол-во пользователей

3) Будет выводиться кол-во администраторов

4) Будет выводиться кол-во поисковых роботов

5) Будет выводиться рекордное кол-во посетителей на сайте

И так, определимся с тем, как мы будем выводить эту информацию на экран.

Если кол-во уникальных посетителей в какой-нибудь категории будет равно 0, то вместо вывода 0, мы будем выводить слово - нет.

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

Приведём пример - есть два пользователя - Иван и Игорь, при нажатии на ссылку они, если скрыты, то покажутся, если видны, то скроются.

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

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

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

Как мы будем осуществлять скрытие или показ информации на экран?

А очень просто! Для этого мы воспользуемся javascript!

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

Код нашего скрипта такой:

<script type = "text/javascript">
// Функция для скрытия/показа ников пользователей/администраторов
function look(type){
param=document.getElementById(type);
if(param.style.display == "none") param.style.display = "block";
else param.style.display = "none"
}
</script>

Сейчас мы Вам объясним как эта функция работает.

Мы передаём функции имя блока

Заносим в переменную param - метод getElementById объекта document, которому передаём id - имя нашего блока, после чего мы сможем изменять стиль этого блока.

В условии проверяем - если блок имеет стиль display:none, то мы его показываем на экран, иначе скрываем.

В этом скрипте нет ничего сложного.

А для того чтобы скрывать тот или иной блок, нужно прописать ссылку, в которой href будет равен вызову javascript функции.

Ссылка будет такой:

<a href = "javascript: look('div1');">Показать/скрыть</a>

А блок будет таким:

<div id = "div1" style = "display:none">Какая-то информация</div>

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

Теперь определимся с тем - как мы будем выводить ники/имена пользователей и т.д.

Кажется всё просто - воспользуемся циклом, но ведь если писать - "имя," - то после последнего имени будет стоять запятая, будет что-то вроде этого - имя1, имя2, имя3,

Для того чтобы избежать этого мы предлагаем сначала написать первое имя без запятой, а после в цикле писать что-то вроде этого - , имя - и тем самым мы получим такую строку - имя1, имя2, имя3 - и не каких лишних запятых.

И если имя будет одно, то цикл не сработает и опять всё выведется нормально!

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

Определять поисковой ли робот или нет, мы будем в начале кода, чтобы не заносить его в базу как гостя.

Для проверки на робота мы воспользуемся супер-глобальным массивом $_SERVER, в котором есть такой элемент как - USER_AGENT, в нём-то и можно проверить - бот ли это или нет.

Для каждого поискового робота используется своё название, и мы в нашей системе сделали проверку на трёх известных роботов - google, yandex и rambler.

Проверять мы будем так:

if ( ( substr ( $_SERVER['USER_AGENT'], 0, 6 ) == 'Yandex' ) || ( substr ( $_SERVER['USER_AGENT'], 0, 11) == 'YaDirectBot' ) ) {
	$bot = 'yandex';
  } else {
	if ( ( strpos ( $_SERVER['USER_AGENT'], 'Googlebot' ) !== false) || ( strpos ( $_SERVER['USER_AGENT'], 'Mediapartners-Google' ) !== false ) || ( strpos ( $_SERVER['USER_AGENT'], 'Google Search Appliance' ) !== false ) ) {
		$bot = 'google';
	} else {
		if ( substr ( $_SERVER['USER_AGENT'], 0, 12 ) == 'StackRambler' ) {
			$bot = 'rambler';
		} else {
			$bot = '';
		}
	}
}

Если поискового робота не будет, то переменной bot мы присвоим пустое значение, конечно можно обойтись и без присваивания переменной пустого значения - просто в условии проверив существует ли такая переменная функцией isset, но мы решили пойти другим путём.

Мы не будем выводить кол-во администраторов на сайте, вместо этого мы будем выводить слова - online или offline, если администраторы в сети или не в сети.

И самое интересное - как же мы будем отличать пользователя от гостя или от администратора, да очень просто!

Мы воспользуемся сессиями, в которые будем заносить имя пользователя и в элемент admin - значения yes или no.

Если нет имени и значения в admin, то это гость.

Если есть имя, но значение admin - no, то это пользователь.

Если есть имя и значение admin - yes, то это администратор.

Но если Вы хотите использовать это на сайте, то лучше всё же использовать такой метод:

Если нет имени в сессии, то это ГОСТЬ

Если есть имя, то проверяем есть ли оно в базе - если нет, то это ГОСТЬ - если есть, то проверяем не администратор ли - если администратор, то добавляем его как администратора в таблицу online, если нет, то добавляем его как пользователя в таблицу online.

Такой метод нужен для избежания того, чтобы кто-то зашёл как администратор, то-есть пользователь может у себя создать скрипт, и в нём сессии присвоить значение администратора, но с методом проверки, такое у него не прокатит!

И так нам понадобится три таблицы - для посетителей, для роботов и для данных о рекорде.

Вот три sql-запроса:

CREATE TABLE IF NOT EXISTS `bot` (
  `name` varchar(255) NOT NULL,
  `date` datetime NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;
CREATE TABLE IF NOT EXISTS `online` (
  `id` tinytext NOT NULL,
  `date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `users` varchar(255) NOT NULL,
  `admin` varchar(3) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;
CREATE TABLE IF NOT EXISTS `record` (
  `record` int(10) NOT NULL,
  `guests` int(10) NOT NULL,
  `users` int(10) NOT NULL,
  `admins` int(10) NOT NULL,
  `date` varchar(255) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=cp1251;

А вот и сам код:

<?php 
  // Начинаем сессию 
  session_start(); 
?>
<html>
<head>
<title>OnLine</title>
<style type = "text/css">
	a {
		color: #006699;
	}
	a:hover{
		text-decoration: none;
	}
</style>
<script type = "text/javascript">
// Функция для скрытия/показа ников пользователей/администраторов
function look(type){
param=document.getElementById(type);
if(param.style.display == "none") param.style.display = "block";
else param.style.display = "none"
}
</script>
</head>
<body>
<?php
  
  // Устанавливаем соединение с базой данных 
  $db = mysql_connect ( "localhost", "root", "" );
  mysql_select_db ( "site", $db );
  
  /*
  * Если на наш сайт зашёл поисковой робот - а мы знаем трёх самых популярных, то
  * заносим его имя в переменную, иначе переменной присваиваем пустое значение
  */
  if ( ( substr ( $_SERVER['USER_AGENT'], 0, 6 ) == 'Yandex' ) || ( substr ( $_SERVER['USER_AGENT'], 0, 11) == 'YaDirectBot' ) ) {
	$bot = 'yandex';
  } else {
	if ( ( strpos ( $_SERVER['USER_AGENT'], 'Googlebot' ) !== false) || ( strpos ( $_SERVER['USER_AGENT'], 'Mediapartners-Google' ) !== false ) || ( strpos ( $_SERVER['USER_AGENT'], 'Google Search Appliance' ) !== false ) ) {
		$bot = 'google';
	} else {
		if ( substr ( $_SERVER['USER_AGENT'], 0, 12 ) == 'StackRambler' ) {
			$bot = 'rambler';
		} else {
			$bot = '';
		}
	}
  }
  
  // Если зашёл человек, то ...
  if ( $bot == '' ) {
  
  // Получаем уникальный id сессии 
  $id_session = session_id(); 
  
  // Проверяем, присутствует ли такой id сессии в базе данных  
  $res = mysql_query ( "SELECT * FROM online WHERE id = '$id_session'" );
  
  // Если нам не удалось связаться с таблицой сессий, то выводим ошибку
  if( !$res ) {
	exit ( "<p>Ошибка в запросе к таблице сессий</p>" ); 
  }
  
  /*
  * Если сессия с таким номером уже существует, 
  * значит пользователь online - обновляем время его последнего посещения 
  * если это админ, то обновляем его как админа, иначе как пользователя, если нет имени в массиве сессий, то
  * обновляем его как гостя
  */
  if( mysql_num_rows ( $res ) > 0 ) {
	// Если есть имя в массиве, то значит - это вошедший пользователь
	if ( isset ( $_SESSION["user"] ) & ( $_SESSION["user"] !== '' ) ) {
		// Заносим его имя в переменную и делаем его имя безопасным, для дальнейшей работе с ним
		$user = trim ( stripslashes ( htmlspecialchars ( $_SESSION["user"] ) ) );
		// Если этот пользователь - админ, то обновляем его в базе как админа
		if ( isset ($_SESSION["admin"] ) & ( $_SESSION["admin"] == 'yes' ) ) {
			if ( !mysql_query ( "UPDATE online SET date = NOW(), users = '$user', admin = 'yes' WHERE id = '$id_session'" ) ) { 
				exit ( "<p>Ошибка при добавлении пользователя</p>" ); 
			}
		} else {
			// Иначе - обновляем его как пользователя
			if ( !mysql_query ( "UPDATE online SET date = NOW(), users = '$user' WHERE id = '$id_session'" ) ) { 
				exit ( "<p>Ошибка при добавлении пользователя</p>" ); 
			}
		}
	} else {
		// Если этот пользователь вошёл как гость, то обновляем его в базе как гостя
		if ( !mysql_query ( "UPDATE online SET date = NOW(), users = '', admin = 'no' WHERE id = '$id_session'" ) ) { 
			exit ( "<p>Ошибка при добавлении пользователя</p>" ); 
		}
	}
  } else { 
	// Если такого id нет в базе, то посетитель только что 
	// вошёл - помещаем в таблицу нового посетителя 
	// Если это пользователь, то
	if ( isset ( $_SESSION["user"] ) & ( $_SESSION["user"] !== '' ) ) {
		// Заносим его имя в переменную и делаем безопасным
		$user = trim ( stripslashes ( htmlspecialchars ( $_SESSION["user"] ) ) );
		// Если в массиве сессий есть значение yes в элементе admin, то добавляем его как админа
		if ( isset ($_SESSION["admin"] ) & ( $_SESSION["admin"] == 'yes' ) ) {
			if ( !mysql_query ( "INSERT INTO online VALUES ('$id_session', NOW(), '$user', 'yes')" ) ) { 
				exit ( "<p>Ошибка при добавлении пользователя</p>" ); 
			}
		} else {
			// Если не админ, но есть имя в массиве сессии, то добавляем его как пользователя
			if ( !mysql_query ( "INSERT INTO online VALUES ('$id_session', NOW(), '$user', 'no')" ) ) { 
				exit ( "<p>Ошибка при добавлении пользователя</p>" ); 
			}
		}
	} else {
		// Если это гость, то добавляем гостя
		if ( !mysql_query ( "INSERT INTO online VALUES ('$id_session', NOW(), '', 'no')" ) ) { 
			exit ( "<p>Ошибка при добавлении пользователя</p>" ); 
		}
	}
  }
  
  }
  
  /*
  * Будем считать, что пользователи, которые отсутствовали 
  * в течении 10 минут - покинули сайт - удаляем их 
  * id_session из базы данных  
  */
  mysql_query("DELETE FROM online WHERE date < NOW() -  INTERVAL '10' MINUTE");
  
  
  echo "<tt>";
  /*
  * Мы будем выводить кол-во гостей, если они есть, то выводим их кол-во,
  * иначе будем выводить слово - нет, вместо 0
  */
  $count_sel = mysql_query ( "SELECT COUNT(*) FROM online WHERE users = ''", $db );
  $count_row = mysql_fetch_array ( $count_sel );
  if ( $count_row[0] > 0 ) {
	echo "Гостей: ".$count_row[0]."<br />";
  } else {
	echo "Гостей: нет<br />";
  }
  
  /*
  * Будем выводить кол-во пользователей, если их больше 0, то выведем ссылку, которая при нажатии на неё
  * будет показывать/скрывать имена пользователей в виде ссылок на их персональные страницы,
  * если пользователей не будет, то слово - пользователей, выведется как простое слово, а не ссылка
  * и вместо 0, будет слово - нет.
  */
  $count_sel = mysql_query ( "SELECT COUNT(*) FROM online WHERE users != '' AND admin != 'yes'", $db );
  $count_row = mysql_fetch_array ( $count_sel );
  if ( $count_row[0] > 0 ) {
	/*
	* Выводим список пользователей, предварительно скрыв их, и делаем ссылку, которая при нажатии может
	* показать, а может и скрыть список пользователей
	* Для того чтобы скрыть/показать список пользователей, мы воспользуемся простым javascript'ом,
	* который будет менять стиль отображения для нашего div блока
	*/
	echo "<a href = \"javascript:look('users');\">Пользователей</a>: ".$count_row[0]."<br />";
	echo "<div id = 'users' style = 'display:none'>";
	// Вытаскиваем список пользователей из таблицы
	$select_users = mysql_query ( "SELECT * FROM online WHERE users != '' AND admin != 'yes'", $db );
	$row_users = mysql_fetch_array ( $select_users );
	// Если пользователи есть, то ...
	if ( mysql_num_rows ( $select_users ) > 0 ) {
		echo "<b>";
		/*
		* Для того чтобы выводить список пользователей через запятую, нужно сначала просто вывести первое имя,
		* а после выводить сообщение в цикле типа - , имя
		*/
		if ( mysql_num_rows ( $select_users ) > 1 ) {
			echo "<a href = 'page.php?name=".$row_users["users"]."'>".$row_users["users"]."</a>";
			$row_users = mysql_fetch_array ( $select_users );
			do {
				echo ", <a href = 'page.php?name=".$row_users["users"]."'>".$row_users["users"]."</a>";
			} while ( $row_users = mysql_fetch_array ( $select_users ) );
			echo "<br />";
		} else {
			echo "<a href = 'page.php?name=".$row_users["users"]."'>".$row_users["users"]."</a><br />";
		}
		echo "</b>";
	}
	echo "</div>";
  } else {
	// Если пользователей нет, то выводим об этом соответствующую информацию.
	echo "Пользователей: нет<br />";
  }
  /*
  * Если админы есть, то выводим он-лайн, иначе офф-лайн.
  * И также как и пользователей в цикле выводим администраторов.
  */
  $count_sel = mysql_query ( "SELECT COUNT(*) FROM online WHERE admin = 'yes'", $db );
  $count_row = mysql_fetch_array ( $count_sel );
  if ( $count_row[0] > 0 ) {
	// Выводим список администраторов, предварительно скрыв их, и делаем ссылку, которая при нажатии может показать, а может и скрыть список администраторов
	$count_sel = mysql_query ( "SELECT COUNT(*) FROM online WHERE users != '' AND admin = 'yes'", $db );
	$count_row = mysql_fetch_array ( $count_sel );
	if ( $count_row[0] > 0 ) {
		echo "<a href = \"javascript:look('admins');\">Администраторы</a>: <font color = 'green'><b>online</b></font><br />";
		echo "<div id = 'admins' style = 'display:none'>";
		$select_admins = mysql_query ( "SELECT * FROM online WHERE users != '' AND admin = 'yes'", $db );
		$row_admins = mysql_fetch_array ( $select_admins );
		if ( mysql_num_rows ( $select_admins ) > 0 ) {
			echo "<b>";
			if ( mysql_num_rows ( $select_admins ) > 1 ) {
				echo "<a href = 'page.php?name=".$row_admins["users"]."'>".$row_admins["users"]."</a>";
				$row_admins = mysql_fetch_array ( $select_admins );
				do {
					echo ", <a href = 'page.php?name=".$row_admins["users"]."'>".$row_admins["users"]."</a>";
				} while ( $row_admins = mysql_fetch_array ( $select_admins ) );
				echo "<br />";
			} else {
				echo "<a href = 'page.php?name=".$row_admins["users"]."'>".$row_admins["users"]."</a><br />";
			}
			echo "</b>";
		}	
		echo "</div>";
  }
  } else {
	// Если администраторов нет, то выводим offline
	echo "Администраторы: <font color = 'red'><b>offline</b></font><br />";
  }
  /*
  * Если есть поисковой робот, то проверяем есть ли он в базе, если есть, то обновляем время его посещения,
  * иначе добавляем его в базу данных
  */
  if ( $bot !== '' ) {
	$bot_res = mysql_query ( "SELECT * FROM bot WHERE name = '$bot'", $db );
	if ( mysql_num_rows ( $bot_res ) > 0 ) {
		if ( !mysql_query ( "UPDATE bot SET date = NOW()" ) ) {
			die ( "Ошибка добавления робота в базу данных" );
		}
	} else {
		if ( !mysql_query ( "INSERT INTO bot VALUES ('$bot', NOW())" ) ) {
			die ( "Ошиба добавления робота в базу данных" );
		}
	}
	}
	
	// Удаляем всех поисковых роботов из базы, которых не было 10 минут
	mysql_query("DELETE FROM bot WHERE date < NOW() -  INTERVAL '10' MINUTE");
	
	// Выводим точно также как и пользователей, только уже кол-во поисковых ботов, и их имена не в виде ссылок
	$count_sel = mysql_query ( "SELECT COUNT(*) FROM bot", $db );
	$count_row = mysql_fetch_array ( $count_sel );
	if ( $count_row[0] > 0 ) {
		echo "<a href = \"javascript:look('bots');\">Поисковых роботов</a>: ".$count_row[0]."<br />";
		echo "<div id = 'bots' style = 'display:none'>";
		$select_bots = mysql_query ( "SELECT * FROM bot", $db );
		$row_bots = mysql_fetch_array ( $select_bots );
		if ( mysql_num_rows ( $select_bots ) > 0 ) {
			echo "<b>";
			if ( mysql_num_rows ( $select_bots ) > 1 ) {
				echo $row_bots["name"];
				$row_bots = mysql_fetch_array ( $select_bots );
				do {
					echo ", ".$row_bots["name"]."</a>";
				} while ( $row_bots = mysql_fetch_array ( $select_bots ) );
				echo "<br />";
			} else {
				echo $row_bots["name"]."<br />";
			}
			echo "</b>";
		}	
		echo "</div>";
  } else {
	echo "Поисковых ботов: нет<br />";
  }
  
  /*
  * Выводим рекордное кол-во человек на сайте.
  * Если их сейчас больше, чем было в прошлом рекорде, то обновляем статистику, занося в базу кол-во
  * пользователей, гостей, администраторов и общее кол-во посетителей, не учитывая поисковых роботов.
  * Если пользователей меньше или столько же, то выводим информацию о рекордном кол-ве посетителей
  */
  $record_res = mysql_query ( "SELECT COUNT(*) FROM online", $db );
  $record_row = mysql_fetch_array ( $record_res );
  $res_record = mysql_query ( "SELECT * FROM record", $db );
  $row_record = mysql_fetch_array ( $res_record );
  if ( $record_row[0] > $row_record["record"] ) {
	$rec = $record_row[0];
	if ( !mysql_query ( "UPDATE record SET record = '$rec'", $db ) ) {
		die ( "Обновить рекорд не удалось!" );
	}
	$record_res = mysql_query ( "SELECT COUNT(*) FROM online WHERE users = ''", $db );
	$record_row = mysql_fetch_array ( $record_res );
	$rec = $record_row[0];
	if ( !mysql_query ( "UPDATE record SET guests = '$rec'", $db ) ) {
		die ( "Обновить рекорд не удалось!" );
	}
	$record_res = mysql_query ( "SELECT COUNT(*) FROM online WHERE users != '' AND admin != 'yes'", $db );
	$record_row = mysql_fetch_array ( $record_res );
	$rec = $record_row[0];
	if ( !mysql_query ( "UPDATE record SET users = '$rec'", $db ) ) {
		die ( "Обновить рекорд не удалось!" );
	}
	$record_res = mysql_query ( "SELECT COUNT(*) FROM online WHERE users != '' AND admin = 'yes'", $db );
	$record_row = mysql_fetch_array ( $record_res );
	$rec = $record_row[0];
	if ( !mysql_query ( "UPDATE record SET admins = '$rec'", $db ) ) {
		die ( "Обновить рекорд не удалось!" );
	}
	$day = date ( "d-m-Y в H:i" );
	if ( !mysql_query ( "UPDATE record SET date = '$day'", $db ) ) {
		die ( "Обновить рекорд не удалось!" );
	}
  }
  $rec_res = mysql_query ( "SELECT * FROM record", $db );
  $rec_row = mysql_fetch_array ( $rec_res );
  echo "Рекордное кол-во человек: <b>".$rec_row["record"]."</b> ( Гостей: <b>".$rec_row["guests"]."</b>, Пользователей:
<b>".$rec_row["users"]."</b>, Администраторов: <b>".$rec_row["admins"]."</b> ) было ".$rec_row["date"];
  echo "</tt>";
?>
Поделиться...
twitter.com facebook.com vkontakte.ru mail.ru google.com bobrdobr.ru
Комментариев: 2
  1. Приму на заметку ! Попробую на свой сайт вставить . Хоть я и в юкозе начинал , но теперь сам пишу сайт , вроде даже получается ... Потом , если получится , выложу адрес .

    Спасибо за статью !

  2. очень полезная вещь. использовала в своем сайте нужно было вычислить вредителя.

Оставьте свой комментарий!

Используйте нормальные имена. Ваш комментарий будет опубликован после проверки.

Если вы уже зарегистрированы как комментатор, укажите пароль и свой действующий email.

(обязательно)