В этой статье подробным
образом описан способ ведения
статистики с помощью счетчика
выполненного на PHP. Статья рассчитана на
низкий/средний уровень
подготовленности программиста по PHP.
Программа, описанная в этой
статье, позволит вам оснастить ваш
вебсайт графическим счетчиком,
выполненным в виде баннера 80*31. Счетчик
позволяет вести подсчет хитов/хостов за
день + хитов за месяц. Основа для
хранения данных о посетителях -
текстовая база данных. Формат базы
следующий:
- Основной файл данных - в него пишутся
все данные про посещаемость вашего
сайта в виде:
160701127.0.0.1 /test/news.html
160701127.0.0.1 /me/index.html
160701127.0.0.2 /me/index.html
Первые 6 цифр - это дата, последующая
группа информации - это ip посетителя,
далее через пробел следует URL страницы,
с которой вызывается наш счетчик. На
языке регулярных выражений формат
записывается следующим образом:
"/^([0-9]{6})([^ ]*)[ ]*([^ ]*)$/"
- Месячный лог-файл - в этот файл
пишутся данные про посещаемость
ресурса по дням в следующем виде:
150701 164
160701 150
170701
Первая группа из 6-ти цифр - это дата,
следующая группа цифр - это количество
хитов за день. В виде регулярного
выражения формат можно записать так:
"/^([0-9]{2})([0-9]{4})[ ]*([^ ]*)$/"
Имея "расписанный" формат
базы данных, можно написать текст модуля,
подсчитывающего кол-во хитов/хостов и
хитов за месяц на основе "готовой"
базы данных посещений (на этапе
тестирования программы вполне
достаточно гипотетической базы данных
из десятка записей).
Текст модуля, считающего
статистику:
function Count($ip)
{
$str_day=$this->getLastDay(); // Функция "дающая"
дату в виде "ддммгг"
# Получаем "рабочую дату" из "месячного"
лог файла, а если ее нет (лог-файл пуст
или, иначе говоря, первый запуск
счетчика - создаем ее)
if ($str_day=="no_day"){$str_day=ShortDay();$this->write_m($str_day);}
# Это для удобства. Все имена лог файлов
хранятся в глобальных переменных
$arr=file($GLOBALS['counter_log_daily']);
# Самое главное в нашем счетчике -
подсчет статистики
$j=0;
for ($i=0;$i
{
if (!preg_match("/^([0-9]{6})([^ ]*)[ ]*([^ ]*)$/",$arr[$i],$var))continue;
if (trim($var[1])==$str_day){$this->hits++;$iparr[$j++]=$var[2];}
}
//Тут идет подсчет хостов за день
$c_iparr = array_count_values ($iparr);
$c_iparr_k = array_keys ($c_iparr);
$this->hosts=count($c_iparr_k);
//$c_iparr_v = array_values($c_iparr);
//Хиты за месяц:
$arr=file($GLOBALS['counter_log_month']);
$hm=0;
for ($i=0;$i
{
if (!preg_match("/^([0-9]{2})([0-9]{4})[ ]*([^ ]*)$/",$arr[$i],$var))continue;
if ($var[2]==date("my")){$hm+=$var[3];}
}
$this->month_hits=$hm+$this->hits;
# Так называемое "закрытие дня" - при
ситуации когда день текущий не
совпадает с днем рабочим записываем в
лог-файл количество хитов за рабочий
день и переводим рабочий день на текущий.
if ($str_day!=ShortDay())
{
$this->write_m(" ".($this->hits)."\n".ShortDay());
$this->hits=1;
}
}
Наиболее интересным моментом в
работе счетчика является защита данных
от "порчи" при применении "многопоточных"
интернет-серверов. В документации по PHP
ясно дается понять, что применять "штатную"
функцию flock() для блокирования лог файлов
нецелесообразно. Поэтому пришлось
выдумать свою, пускай и несколько
наивную, схему блокировки. Смысл ее
состоит в следующем: для каждого лог-файла,
для которого существует возможность
одновременной записи и чтения
информации, до записи создается id файл .
После записи он уничтожается. Если "второй"
процесс заметил существование такого
файла, то он ждет 1с на его уничтожение.
Подобное реализуется в
следующей функции:
function is_month_lock() <--- есть есть id,
файл возвращает 1, иначе - 0
function month_lock() <--- Создает ид файл
function month_unlock() <--- Уничтожает id файл
function write_m($str)
{
$i=0;
$write_ok=0;
while ($i<20 && $write_ok==0) <--- Всего 20
циклов ожидания уничтожения файла
{
if (!$this->is_month_lock())
{
$this->month_lock();
$lf=$GLOBALS['counter_log_month'];
$fp = fopen ($lf,"a+");
fwrite($fp,$str);
fflush($fp);
fclose($fp);
$this->month_unlock();
$write_ok=1;
}
else
{
usleep(50000); <--- Один цикл ожидания
$i++;
}
}
if ($write_ok!=1)$this->month_unlock(); <--- Защита от
"сбойного" поведения PHP. Для
спокойствия (на медленных серверах)
можете увеличить количество периодов до
100 шт.
return $write_ok;
}
В конце приведу текст модуля,
выводящего на экран рисунок со
счетчиком. В особенных пояснениях текст,
я думаю, не нуждается. Однако если
вопросы возникнут - читайте статьи на
сайте "Программы для бизнеса",
посвященные работе с графикой в PHP (см.
ниже "Ссылки по теме").
function MakePNG ($imgname,$_hi,$_ho,$_ha)
{
$m=$GLOBALS['counter_max_digits'];
$hi=AddSpaces($_hi."",$m,"l");
$ho=AddSpaces($_ho."",$m,"l");
$ha=AddSpaces($_ha."",$m,"l");
$im = @ImageCreateFromPNG ($imgname); /* Attempt to open */
$tc = ImageColorAllocate ($im, 0, 0, 60);
if (!$im)
{
$im = ImageCreate (80, 31); /* Create a blank image */
$bgc = ImageColorAllocate ($im, 255, 255, 255);
ImageFilledRectangle ($im, 0, 0, 150, 30, $bgc);
}
$l=81-6*$m;
ImageString ($im, 2, $l, -1, $hi,$tc);
ImageString ($im, 2, $l, 19, $ho ,$tc);
ImageString ($im, 2, $l, 9, $ha ,$tc);
return $im;
}
function OutPut()
{
$im = $this->MakePNG("png.png",$this->month_hits,$this->hosts+0,$this->hits+0);
ImagePng ($im);
ImageDestroy ($im);
}
Полный исходный текст
программы вы можете взять на сайте "Программы
для бизнеса" в разделе "Загрузка".
Перейти >>>
Ccылки по теме:
- Исходный текст статьи на сайте "Программы
для бизнеса." Перейти
>>>
- Статья "Начинаем работу с
рисунками в php для Windows." Перейти
>>>
- FAQ PHP на сайте "Программы для
бизнеса." Перейти
>>>
Кириллов Арсен г.Львов 2001 г. softm@ukr.net
|