Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

А сколько человек на сайте?

Автор: Makswell
Источник: http://progers.ru/

Всем доброго времени суток!

Наверняка, гуляя по сети в поисках порн..., т.е. в поисках какой-либо информации, вы натыкались на такую фишку, типа:

На сайте: 100 человек

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

Недавно, по личной надобности, мне захотелось сделать такое для своего сайта и я реализовал все это дело с использованием PHP+MySQL. На нашем портале Progers.ru вы можете видеть (вверху) красующуюся надпись о количестве пользователей On-Line.

Итак, в этой статье я хочу вам рассказать, как сделать такую фичу для сайта. Это на самом деле проще жареной капусты ;=) и вскоре вы убедитесь в этом.

Все что нам нужно, это - хостинг с поддержкой 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  // вставляем свою запись
$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 - переменная, определяющая формат вывода
 $line = "человека"; else $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=).

Из добавлений, пожалуй, все. Да и статье приходит Зе Енд. Рад, что вы дочитали пособие до этого места, а еще большее эстетического наслаждение мне принесет тот факт, что статья показалось вам занимательной и оставила хорошие впечатления и знания в баш... голове. Если вы заметили ошибки\неточности\баги в статье или у вас что-то не получилось, то оставляйте комменты ниже или пишите на мыло. Я обязательно вас выслушаю и отвечу. Естественно, буду рад и добрым пожеланиям. Как же без них. Хотя критика принесет мне большую пользу...

Пример работы функции подсчета посетителей On-Line вы можете увидеть на нашем портале - Progers.Ru. Кроме этого, здесь вы можете найти много хороших статей и справочников по программированию, в частности, на PHP, с использованием MySQL.

На этом позвольте проститься с вами и пожелать удачи и... конечно же, попутного кода!

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

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 

Комментарии

1.
100.0M
11 января 2020 года
Liza Kond
0 / / 11.01.2020
Мне нравитсяМне не нравится
11 января 2020, 18:45:05
Спасибо, шикарная статья! Все по делу и понятно ...
По определению пользователей сейчас уже много решений для определения. появились такие сервисы, позволяющие узнавать не только IP, но и телефонные номера всех посетителей сайта. используют в маркетинге для обзвонов. говорят, что легально - патенты, резрешения, все дела. как они это делают? пример - https://vse-klienty.ru
2.
96K
06 декабря 2015 года
Виктор Фикус
0 / / 06.12.2015
+1 / -2
Мне нравитсяМне не нравится
6 декабря 2015, 20:09:13
/* ф-я подсчитывает пользователей на линии; возвращает кол-во пользователей в
отформатированном виде, т.е. для вывода результата нужно лишь прописать в
нужном месте типа: 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 // вставляем свою запись
$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 - переменная, определяющая формат вывода
$line = "человека"; else $line = "человек";
// возвращаем результат
return "На сайте <strong>".$online_people."</strong>$line";
}
я спршую пачму оно не роботоить што ты замусар на писал да прогмить с куплиным дипломам
3.
Аноним
+2 / -2
Мне нравитсяМне не нравится
28 февраля 2006, 09:20:35
"Можно в связку добавить еще какую-нить уникальную информацию, например браузер клиента."
Уникальнее, информацию придумать трудно :-)))
4.
Аноним
+0 / -1
Мне нравитсяМне не нравится
10 февраля 2006, 18:39:00
Использование MySQL для этих целей - как минимум глупа! Добавлять в список online нужно по связке IP/COOKIE - таким образом будет подсчитано максимально реальное число клиентов. Можно в связку добавить еще какую-нить уникальную информацию, например браузер клиента.
Для решения траблы с таймаутом, заюзать javascript, через скрытый фрейм посылать своеобразный ping скрипту, который получив запрос, обнулял счетчик таймаута. Еще можно поставить обработчики событий на закрытие браузера и переход на др. сайт в BODY onUnLoad, по которому скрипт выкидывает клиента.
5.
Аноним
Мне нравитсяМне не нравится
18 ноября 2005, 15:44:24
[QUOTE]а если в течении суток никто на сайт
не зайдёт, тоесть скрипт не запуститься, то эти пользователи так и будут висеть в списке online[QUOTE]
По-моему, здесь нет ничего плохого. Пока никто не заходит на сайт, никто и не видит, сколько юзеров считаются присутствующими, а как только кто-то появляется, сразу происходит пересчет, и новый юзер видит адекватную информацию.
6.
Аноним
Мне нравитсяМне не нравится
14 сентября 2005, 08:12:21
по моему удобнее делать это так же при помощи таблицы, однако занести это дело в какой либо глобальный класс. запускать сессию, при завершении сесси (закрытие окна браузера), вычитать человека из таблицы.
7.
Аноним
Мне нравитсяМне не нравится
15 августа 2005, 16:24:32
Спасибо!
А если пользователь сидит на сайте больше чем время точности
То как я понял сервер буит считать что на сайте его уже нет хотя пользователь там будет
Вплоть до того что если точность будет 10 минут и на сайт войдут 20 пользователей за первую минуту
то посиди они на сервере больше десяти минут и скрипт покажет что пользователей нет а на самом деле их будет 20!!!!
Но функция time мне понравилась!
И скрипт обновления кол- ва пользователей (тоесть удаление пользователей подходящих под условие точности) запускаеться когда пользователь заходит на сайт, а если в течении суток никто на сайт
не зайдёт, тоесть скрипт не запуститься, то эти пользователи так и будут висеть в списке online
тоесть реально опрос пользователей online проходит когда кто- то зашел на сайт!
8.
Аноним
+1 / -0
Мне нравитсяМне не нравится
28 июля 2005, 11:37:48
если отбросить тех, у кого выключены куки, то можно легко смотреть в каталог где лежат сесии и смотреть на время доступа к файлу_сессии и считать количество файлов.
9.
Аноним
+1 / -0
Мне нравитсяМне не нравится
20 мая 2005, 14:38:13
<blockquote><small>Цитата:<hr size=1>Это заблуждение. Сессия уничтожается по таймату. Закрытие браузера выловить никак нельзя.[/quote]

Если у пользователя влючены cookies, то можно воспользоваться переменными сессии, которые хранятся до закрытия браузера в массиве $_SESSION[]!
10.
Аноним
+2 / -1
Мне нравитсяМне не нравится
19 мая 2005, 13:59:52
<blockquote><small>Цитата:<hr size=1>В этом случае мы точно будем знать когда человек покинул сайт(закрыл браузер).[/quote]
Это заблуждение. Сессия уничтожается по таймату. Закрытие браузера выловить никак нельзя.
11.
Аноним
Мне нравитсяМне не нравится
19 мая 2005, 10:48:14
Статья интересная, но не легче-ли будет организовать счетчик на основе сессий? В этом случае мы точно будем знать когда человек покинул сайт(закрыл браузер). И к тому же количество кода гораздо уменьшилось бы...
12.
Аноним
+1 / -0
Мне нравитсяМне не нравится
6 мая 2005, 16:17:33
В принципе идея правильная, но есть одно замечание.
Использовать в качестве идентификатора пользователя его ИП немного некорректно. Тут необходимо учитывать, что несколько пользователей могут сидеть за одним анонимным прокси, или в одной сети, где доступ в Инет есть лишь у одного компутера. В этих ситуациях ИП у них будет одинаковый. Поэтому, ИМХО, лучше использовать идентификатор сессии вместо ИП. Вот.
13.
Аноним
+1 / -0
Мне нравитсяМне не нравится
21 апреля 2005, 15:04:48
Отличная статья :)
14.
Аноним
Мне нравитсяМне не нравится
7 апреля 2005, 22:04:19
Жду ваших отзывов =)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог