И сколько человек на сайте ?
                  Всем доброго времени суток! 
                  Наверняка, гуляя по сети в поисках порн..., т.е. в поисках 
                  какой-либо информации, вы натыкались на такую фишку, типа: 
                  На сайте: 100 человек 
                  Т.е., когда примерно в таком контексте выводится количество 
                  человек, присутствующих в данное время на сайте. Когда я 
                  впервые увидел такую фичу, мне она показалось интересной и 
                  симпотной. 
                  Недавно, по личной надобности, мне захотелось сделать такое 
                  для своего сайта и я реализовал все это дело с использованием 
                  PHP+MySQL. 
                  Итак, в этой статье я хочу вам рассказать, как сделать 
                  такую фичу для сайта. Это на самом деле проще жареной капусты 
                  ;=) и вскоре вы убедитесь в этом. 
                  Все что нам нужно, это - хостинг с поддержкой PHP и MySQL и 
                  пара минут времени. Может быть, некоторые возразят, зачем 
                  здесь база данных, когда все можно реализовать на файлах. 
                  Скажу вам , что MySQL в данном конкретном случае подходит как 
                  нельзя лучше. С использованием файлов же, пришлось бы писать 
                  гораздо больше кода и заниматься в большинстве своем рутиной, 
                  которая нам ни к чему; в то время как с помощью базы данных 
                  все делается парой-другой запросов... 
                  Я надеюсь, что вы умеете хоть как-то обращаться с сервером 
                  MySQL и знаете в целом, что такое базы данных и для чего они 
                  служат. В противном случае, не могу ничем помочь, кроме как 
                  посоветовать обратиться к друзьям, владеющим искусством 
                  составлять SQL-запросы... Хотя, в принципе, вы можете просто 
                  скопировать мой код и все. Однако, сама база данных все же 
                  должна быть настроена... 
                  Итак, постепенно переходим от теории к практической 
                  эпостаси. В PHP, к сожалению (да и в других серверных языках 
                  веб-программирования), отсутствует такая, на мой взгляд, 
                  полезная технология, которая позволяла бы определять момент 
                  времени, в который человек покинул сайт. Неважно, каким 
                  способом, он это сделал: закрыл окно броузера или перешел по 
                  другой ссылке. Раз PHP пасует, сами сделаем кое-какую подобную 
                  технологию; естественно, о точности и отсутствии погрешностей 
                  здесь не говорю... Однако, все так делают и мы так сделаем. 
                  Далее опишу, как мы будем, собственно, определять кол-во 
                  юзеров на линии теоретически (не касаясь MySql и PHP 
                  конкретно). Если вы уловите мысль, то тотчас же реализуете эту 
                  возможность на любом языке веб-программирования и любым 
                  доступным для вас методом (файлы, к примеру)... 
                  Для начала, нам нужно установить переменную 
                  Точность - время, в течении которого 
                  посетитель будет считаться на линии, т.е. бродящем по сайту. 
                   Значит, при заходе на страницу, мы должны определить 
                  сперва-наперво IP-адрес зашедшего и его 
                  timestamp. Никакой экзотики, 
                  TimeStamp - это представление времени, 
                  которое равняется "кол-ву секунд, прошедших с полуночи 1 
                  января 1970 года по Гринвичу до настоящего момента". Это 
                  весьма универсальное представление времени и, в частности, 
                  именно с этим форматом работает большинство PHP-х ф-й для 
                  работы с "датой-временем". Весьма удобная метка, поверьте мне 
                  на слово. Т.е., чем больше число TimeStamp, 
                  чем дольше "мы живем" и чем больше "сейчас времени", извиняюсь 
                  за сумбурность. После, мы открываем какое-либо хранилище 
                  (файлы, базы данных, сессионный массив и т.п.) и удаляем из 
                  него все записи (каждая запись - информация об одном зашедшем 
                  на страничку пользователе), в которых TimeStamp + 
                  Точность меньше текущего TimeStamp'а, или где 
                  IP-адрес совпадает с текущим Ip'м. Т.е., уничтожаем старые 
                  записи.  Далее записываем данные о зашедшем пользователе 
                  (оставляем запись): IP и timestamp.  Все, подсчитываем 
                  количество записей - это и есть кол-во человек на сайте в 
                  данное время. 
                  Честно говоря, получилось так, что ориентир все равно велся 
                  на MySQL, а не на файлы. В самом деле, наше ли это дело, 
                  сначала лезть в файл и удалять там-то, потом опять лезть в 
                  него, чтобы записать, а потом только считывать. Куда проще 
                  сначала считать файл в массив, удалить из массива старые 
                  записи и добавить запись о юзере, если это требуется и уж 
                  потом записать массив обратно в файл. При выводе данных же 
                  руководствоваться кол-м значений в массиве. 
                  Надеюсь, основную мысль вы все же уловили. Мы просто 
                  подсчитываем кол-во юзверей, со времени захода которых не 
                  прошло время, которое мы установили (Точность). 
                  Итак, переходим наконец-то к практике. Повторюсь, для 
                  хранения информации будет юзаться база MySQL. Для всего этого 
                  дела мы создадим отдельную таблицу. Назовем её 
                  online. В таблице создадим 3 поля: 
                  id - ключевое 
                    авто_инкрементирующееся поле типа INT с максимальным 
                    размеров в 10 символов. Нужно для более оптимизированной 
                    работы с таблицой, хотя его можно и опустить. При каждом 
                    заходе человека на сайт, поле будет увеличивать свое 
                    значение на 1. 
                    - ip - поле символьного типа VARCHAR с 
                    максимальным значением 20 cимволов (лично я не видел еще 
                    IP-адреса, размером больше 15 символов, но на всякий случай 
                    =). В нем хранятся, соответственно, IP'ы людей. Значение по 
                    умолчанию - 0. 
                    
 - unix - поле символьного типа VARCHAR с 
                    максимальным значением 60 символов. Поле, в котором будет 
                    храниться timestamp пользователя. Такое странное название 
                    выражено скорее моими личными пристрастиями, чем истинным 
                    его предназначением. Хотя скажу, что timestamp-формат принят 
                    в операционных системах UNIX, как стандарный. Можете поле 
                    назвать как угодно (только мой пример с этим именами полей). 
                    По дефолту пустое значение. 
  
                  Замечу, что поле unix будет иметь тип VARCHAR, а не 
                  встроенный разработчиками MySQL тип TIMESTAMP. Это связано с 
                  тем, что этот тип слишком неудобен для хранения данных 
                  даты\времени в базе, как это может показаться на первый 
                  взгляд. 
                  Далее привожу запрос, выполнив который, вы создадите 
                  соответствующую таблицу с нужными полями. Запрос можно 
                  выполнить функцией PHP mysql_query(), либо в 
                  какой-нибудь удобной оболочке для работы с MySQL. Например в 
                  PHPMyAdmin. 
                  CREATE TABLE `online` ( `id` int(10) NOT NULL 
                  auto_increment, `ip` varchar(20) NOT NULL default 
                  '0', `unix` varchar(60) NOT NULL default '', KEY `id` 
                  (`id`) ) 
                  Выполнили? Молодцы. Напомню, что команды синтаксиса MySQL 
                  лучше всего привыкать писать в верхнем регистре и не для 
                  понта, как думают некоторые, а для повышении удобочитаемости 
                  кода и просто потому, что так принято. 
                  После выполнения запроса, нам остается только написать код, 
                  который будет заниматься, собственно, подсчетом кол-а человек 
                  на линии. Этот код я запихнул в отдельную функцию, которая 
                  хранится у меня в файле, а сам файл инклюдится ( include(), 
                  require() ) на каждой странице моего сайта где-нибудь в самом 
                  начале. Я привожу вам пример функции точь-в-точь, какую я 
                  написал для своего сайта, разве только немного измененную в 
                  целях публичного использования. При наличии необходимых 
                  знаний, вы легко сможете отредактировать её под себя. 
                  #------ Файл online.php
  /* ф-я подсчитывает 
                  пользователей на линии; возвращает кол-во пользователей в 
                  отформатированном виде, т.е. для вывода результата нужно лишь 
                  прописать в нужном месте типа: echo on_line(); */ function 
                  on_line() { $host = "localhost"; // хост, где расположена 
                  база данных MySql $db_name = ""; // имя базы данных; как 
                  правило совпадает с именем юзера (переменная ниже), хотя я 
                  категорически против одинаковых имен, ориентируясь на 
                  защиту... $db_user = ""; // пользователь, которому разрешен 
                  доступ к базе $db_password = ""; // пароль 
                  пользователя $wine = 300; // точность он-лайн (секунды); 
                  время, в течении которого пользователя, зашедшего на 
                  страничку, мы считаем находящимся на сайте $table_online = 
                  "online"; // имя таблицы
  // делаем доступной глобальную 
                  переменную ИП-адреса global $REMOTE_ADDR;
  // 
                  соединяемся с сервером MySQL и выбираем нужную 
                  базу mysql_connect($host,$db_user,$db_password) or 
                  die(mysql_error()); mysql_select_db($db_name) or 
                  die(mysql_error());
  // удаляем всех, кто уже пробыл 
                  $wine секунд или у кого ИП текущий $sql_update = "DELETE 
                  FROM $table_online WHERE `unix`+$wine < ".time()." OR `ip` 
                  = '$REMOTE_ADDR'"; $result_update = 
                  mysql_query($sql_update) or die(mysql_error());
  // 
                  вставляем свою запись $sql_insert = "INSERT INTO 
                  $table_online VALUES 
                  ('','$REMOTE_ADDR','".time()."')"; $result_insert = 
                  mysql_query($sql_insert) or die(mysql_error());
  // 
                  считаем уников он-лайн $sql_sel = "SELECT `id` FROM 
                  $table_online"; $result_sel = mysql_query($sql_sel) or 
                  die(mysql_error());
  $online_people = 
                  mysql_num_rows($result_sel); // кол-во On-Line пользователей 
                   $online_people = (string) $online_people; // приводим к 
                  строковому типу (так надо.. см. дальше)
  $rain = 
                  strlen($online_people) - 1; // номер последнего символа в 
                  числе on-line юзеров
  // форматирование вывода (я все 
                  сделал за вас 
                  =) if($online_people[$rain]==2||$online_people[$rain]==3 ||$online_people[$rain]==4 ||(strlen($online_people)!=1&&$online_people[strlen($online_people)-2]!=1)) $line 
                  = "человека"; else $line = "человек"; // $line - переменная, 
                  определяющая формат вывода
  // возвращем 
                  результат return "На сайте 
                  <strong>".$online_people."</strong>$line"; } 
                   
                  Вот такая вот функция. Где-нибудь в начале файла вам надо 
                  будет вставлять её как-нибудь по типу: 
                  include 'online.php'; 
                  А в том месте, где нужно вывести кол-во пользователей, 
                  писать: 
                  echo on_line(); 
                  Теперь разъясню немного код функции, так как в ней самой я 
                  все подробно откомментировал. Сначала идут переменные, нужные 
                  для удачного коннекта к базе, а также переменная 
                  $wine - наша точность. Также делается 
                  доступной из функции глобальная переменная 
                  $REMOTE_ADDR, которая возвращает IP-адрес 
                  клиентского компьютера. После происходит соединение с сервером 
                  MySQL. И уже после начинается самое интересное. 
                  Первым запросом к базе ( запросы выполняются ф-й 
                  mysql_query() ) мы удаляем все записи, в 
                  которых timestamp + $wine меньше текущего 
                  timestamp или в которых ИП-адрес совпадает с нашим. Т.е. мы 
                  удаляем из таблицы либо старых пользователей, либо самих себя, 
                  чтобы не повторяться. 
                  Вторым запросом мы вставляем свою запись со своим IP'м и 
                  timestamp'м. Обратите внимание ,что значение первого поля мы 
                  оставляем пустым, так как оно инкрементируется от вставки к 
                  вставке и само собой заполнится (увеличенным на 1 предыдущим 
                  значением). 
                  После всех манипуляций с таблицой, в ней остается 
                  действительно истинное кол-во человек на сайте, с момента 
                  прихода которых не прошло $wine секунд. Нам остается лишь 
                  простым запросом выбрать все записи и подсчитать их кол-во. 
                  Это и будет кол-во пользователей в Он-Лайне. Обратите 
                  внимание, что мы с вами, как люди умные, не выбираем сразу все 
                  поля из всех записей (зачем нам лишние данные, если нужно 
                  только подсчитать количество записей), а выбираем только поле 
                  id. Это тоже прием для оптимизации запросов, 
                  хотя многие о нем забывают или не знают. 
                  А вот потом идет, собственно, форматирование данных. На мой 
                  взгляд, я сделал его очень лаконичным и элегантным. Смотреть 
                  приятно, хотя с первого раза и не совсем понятно, как 
                  происходит процесс. Возможно, такое форматирование вам не 
                  понадобится. Вдруг вы захотите как-либо по-другому выводить 
                  информацию о кол-во юзверей. Тогда вам остается или убрать 
                  форматирование, или подредактировать его (в том числе и под 
                  свой дизайн). Так или иначе, переменная 
                  $online_people хранит кол-во пользователей и 
                  дальше вы вольны делать с ней все, что хотите. Можете просто 
                  возвратить её ( return $online_people; ) и сам 
                  формат данных осуществлять при непосредственном выводе, а не в 
                  теле функции, либо вообще, как я уже говорил, не осуществлять 
                  форматирования: 
                  echo "On-Line: ".on_line() 
                  Возможно, так будет даже красивее. 
                  Важные замечания: 
                  
                    - Переменная $wine на моем сайте равна 
                    300 секундам, т.е. 5 минутам. Вы можете произвольно 
                    выставить её значение. 
                    
 - При коннекте к базе и выполнении запросов мы используем 
                    конструкцию or die(), которая в случае 
                    неудачного действия завершает сценарий, но перед этим 
                    выводит в выходной поток (броузер) какую-либо строку. В 
                    нашем случае мы применяем ф-ю 
                    mysql_error(), которая возвращает в 
                    строковом виде ошибку, случившуюся во время манипуляции с 
                    базой\таблицой. Если вы не хотите завершать сценарий (в 
                    самом деле, зачем это надо: ведь из-за одной ошибки в ф-и 
                    сайт перестанет работать!), то просто не используйте эту 
                    конструкцию. Тем более что при какой-либо ошибке и наличии 
                    этой конструкции, пользователь, возможно (если ошибка при 
                    соединении с сервером), сможет узнать некоторые данные 
                    вашего сервера MySQL, а именно хост, логин пользователя и 
                    имя базы, что чревато взломом сайта (я пессимист по натуре - 
                    не верьте мне). 
                    
 - Переменную $online_people мы приводим к 
                    строковому типу, так при формате информации (проверке, что 
                    выводить: "человек" или "человека") мы "крутим строкой"! Как 
                    мы крутим - думаю, разберетесь сами, после некоторого 
                    брожжения мозгов :-). Возможно, можно было сделать все 
                    элегантнее и написать меньше кода - не знаю... Если вы так 
                    считаете, то пишите на е-майл с кодом, 
                    который, на ваш взгляд, лучше моего... или оставляйте 
                    комментарии к этой статье. Я их просматриваю иногда 
                    (периодически раз в полгода ...=) 
                    
 - Ф-я time() занимается тем, что 
                    возвращает время в секундах, прошедшее с полуночи 1 января 
                    1970 года по Гринвичу до настоящего момента. Но мы то знаем, 
                    что по научному это называется TimeStamp... 
                    $-) 
                    
 - Форматирование я разделил символами перехода строки, 
                    т.к. строка проверок (где много знаков || =) очень длинная, 
                    а это приводит к растяжению статьи в ширину, в результате 
                    чего становится очень неудобно производить чтении статьи, 
                    т.к. глаза бегают туда-сюда-обратно (я не о том, что вы 
                    подумали). Вообщем вы меня поняли. 
                    
 - Код рабочий - у меня такой же =) Но: несколько 
                    дополнений были сделаны только при написании статьи, в 
                    частности: 
                    
                      - Добавлены переменные для коннекта к базе и коннект 
                      происходит внутри функции. Естественно, у меня на сайте он 
                      происходит задолго до этого и ф-я, используя открытое 
                      соединение с MySQL-демоном, выполняет запросы. 
                      
 - Форматирование я разделил символом перевода строки 
                      (причину см. выше), так что, если сценарий не заработает и 
                      выдаст тупую ошибку, типа parse error in 
                      ..., то преобразуйте строку проверок в единое 
                      целое (чтобы на одной строчке все было). Но, я думаю, вы 
                      меня поняли. 
                      
 - Ошибки маловероятны, но возможны, так как я правил 
                      комменты и т.п. при написании статьи, вдруг какой-нибудь 
                      символ точки с запятой забыл. Исправляйте все сами 5=). 
                      
    
                  Из добавлений, пожалуй, все. Да и статье приходит Зе Енд. 
                  Рад, что вы дочитали пособие до этого места, а еще большее 
                  эстетического наслаждение мне принисет тот факт, что статья 
                  показалось вам занимательной и оставила хорошие впечатления и 
                  знания в баш... голове. 
	Автор: Makswell 
			  Источник: www.progers.ru 
		  
     |