Главная » Полезные статьи » Язык PHP » Как написать графический счетчик на PHP
Распечатать статью

Как написать графический счетчик на PHP

В этой статье подробным образом описан способ ведения статистики с помощью счетчика выполненного на PHP. Статья рассчитана на низкий/средний уровень подготовленности программиста по PHP.

Программа, описанная в этой статье, позволит вам оснастить ваш вебсайт графическим счетчиком, выполненным в виде баннера 80*31. Счетчик позволяет вести подсчет хитов/хостов за день + хитов за месяц. Основа для хранения данных о посетителях — текстовая база данных. Формат базы следующий:

1. Основной файл данных — в него пишутся все данные про посещаемость вашего сайта в виде:

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})([^ ]*)[ ]*([^ ]*)$/»

2. Месячный лог-файл — в этот файл пишутся данные про посещаемость ресурса по дням в следующем виде:

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; }

В конце приведу текст модуля, выводящего на экран рисунок со счетчиком. В особенных пояснениях текст, я думаю, не нуждается.

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); }

 

Источник:  npksv.ru

Вы можете оставить комментарий, или обратную ссылку на Ваш сайт.

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

Похожие статьи