Notice: Constant articledir already defined in /var/www/students/public_html/pages/pm01/zrr/constants.php on line 2

Notice: Constant articlelist already defined in /var/www/students/public_html/pages/pm01/zrr/constants.php on line 3

Notice: Constant bkcolor already defined in /var/www/students/public_html/pages/pm01/zrr/constants.php on line 5

Notice: Constant frontcolor already defined in /var/www/students/public_html/pages/pm01/zrr/constants.php on line 6

Notice: Constant newsfile already defined in /var/www/students/public_html/pages/pm01/zrr/constants.php on line 7
zRrr - Пишем счетчик
Новости Статьи Гостевая Ссылки О Сайте

Пишем счетчик обращений

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

Для начала нужно где-то сохранить число показов страницы, поскольку данные между обращениями к счетчику в памяти не сохраняются. Вариантов в общем случае два: файл и база данных. Последнее не всгда доступно, впрочем нам для маленького скрипта и не надо. Вот если бы мы делали "систему интернет-статистики", как написано на ХотЛоге... Короче, план такой: открываем файл, считываем из него число, выводим (красиво), увеличиваем число и записываем его в файл. Приступаем:

function Counter($id)             //счетчик сделаем в виде функции, чтобы потом не 
{                                 //вставлять весь этот код в текст страницы. 
  $fname = "cnt".$id.".txt";      //формируем имя файла. что-то вроде cnt01.txt 
  if(!file_exists($fname)):       //если файл не существует 
    $cnt = 0;                     //то обнуляем счетчик
  else:
    $fc = @fopen($fname, "r")     //иначе открываем файл для чтения
    if ($fc):                     //проверяем, открылся ли файл 
      $cnt = fgets($fc);          //читаем строку 
      fclose($fc);                //закрываем файл 
    else:
      $cnt = 0;                   //если не открылся, то обнуляем счетчик 
    endif;
  endif;

//теперь в переменной $cnt - число обращений до нас

  $fc = @fopen($fname, "w")       //открываем файл для записи
    or die('<B>Ошибка при открытии файла для записи.</b>');
    //А если не получилось, завершаем выполнение скрипта и выводим сообщение.
  fwrite($fc, ++$cnt);            //увеличиваем $cnt на 1 и сохраняем новое значение

  return($cnt);                   //возвращаем значение счетчика 
}

Теперь достаточно в нужном месте на странице вставить <?php print(Counter('01')); ?> и пользователь, загрузивший страничку увидит например: "Вы - 1024 посетитель нашего сайта." Страничка, правда, должна иметь расширение .php что бы все заработало. Функцию можно убрать в другой файл и вызывать по мере необходимости, предварительно написав include "counter.php";.

Первую часть функции можно переписать короче:

  if (!$fc = @fopen($fname, 'r')):
    $cnt = 0;
  else:
    $cnt = fgets($fc);
  endif;

или еще короче:

  $cnt = (!$fc = @fopen($fname, 'r')) ? 0 : fgets($fc);

Что мы использовали:

  • file_exists(строка имя_файла) - возвращает TRUE если указаный файл существует, иначе - FALSE.
  • fopen(строка имя_файла, строка режим) - связывает переменную-ресурс с файлом. Файл может быть как на локальной машине так и в Интернете. Параметр режим определяет тип доступа к файлу: "r" - чтение с начала файла, "r+" - чтение и запись с начала файла; "w" - перезапись файла, "w+" - перезапись и чтение; "a", "a+" - добавдение в файл. Если файл не удается открыть, функция возвращает FALSE.
  • fgets(ресурс дескриптор, [целое длина]) - возвращает строку из ранее открытого файла, размером длина - 1 байт. С версии PHP 4.3 опускание параметра длина приводит к чтению строки до конца. При возникновении ошибки функция возвращает FALSE.
  • fwrite(ресурс дескриптор, строка строка [, целое длина]) - выводит строку в файл. Если указан параметр длина, то процесс остановится, когда будет записано столько байт, если строка не будет записана целиком раньше. Если возникнет ошибка, функция вернет FALSE, иначе - число заисаных байт.
  • fclose(ресурс дескриптор) - закрывает ранее открытый файл. Возвращает TRUE если все в порядке и FALSE в противном случае.
  • die(строка сообщение) - завершает выполнение скрипта и выводить сообщение Вместо строки можно подставить целое, но оно выведено не будет. Это синоним функции exit(), который, лично мне, встречался чаще. Видимо, авторами виденых скриптов были очень кровожадные люди :).

Оператор @ в последнем примере подавляет вывод ошибок при выполнении fopen(). На время отладки лучше его не ставить, а так пользователю совсем не обязательно знать, почему он всегда первый посетитель :). Файл может не открыться, например, из-за неверно выставленых прав доступа (должны быть права на чтение и запись для всех групп, т.е. '666').

Модернизируем наш счетчик. Теперь он должен будет выводить еще и количество посетителей за сегодняшний день. Для этого мы будем сохранять в файле дату последнего обращения (день, месяц, год), число посетителей в этот день и общее число посетителей. При обращении, будем сравнивать дату с текущей, и если она не совпадет, обнулять счетчик. Поехали:

function Counter($id)               
{                                   
  $fname = "cnt".$id.".txt";        
  if (!$fc = @fopen($fname, 'r')): //если файл открыть не получилось 
    $cnt  = 0;
    $date = date('dmY');          //обнуляем счетчики и выставляем текущую дату 
    $dcnt = 0;
  else:
    $cnt  = fgets($fc);           //иначе считываем основной счетчик
    $date = trim(fgets($fc));     //дату, и одновременно отрезаем символы конца строки
    $dcnt = fgets($fc);           //и счетчик за сегодня
  endif;
  
  $cnt = $cnt + 1;                //увеличиваем основной счетчик (автоматически приводим к целому типу)
  if (date('dmY') == $date):      //если дата не изменилась
    $dcnt = $dcnt + 1;            //увеличиваем счетчик за сегодня
  else:
    $dcnt = 1;                    //иначе сбрасываем
    $date = date('dmY');          //и берем новую дату
  endif;

  $fc = @fopen($fname, "w")
    or die('<B>Ошибка при открытии файла для записи.</b>');
  fwrite($fc, $cnt."\r\n");       //сохраняем
  fwrite($fc, $date."\r\n");
  fwrite($fc, $dcnt."\r\n");

  $res['cnt'] = $cnt;             //возвращать результат будем в виде массива
  $res['dcnt'] = $dcnt;

  return($res);
}

Поскольку возвращаем мы значения в виде массива, вывод будет выглядеть чуть иначе: Вы <?php $r = Counter('01'); print("{$r['cnt']} ({$r['dcnt']} за сегодня)"); ?> - посетитель этого сайта!.

  • trim(строка строка [, строка список_символов]) - удаляет пробелы и некоторые спец. символы (табуляция, конец строки...) из начала и конца строки. Используйте список_символов для указания символов для удаления. Возвращает обрезаную строку.
  • date(строка формат [, строка метка_времени]) - возвращает строку с текущей датой/временем, в формате, задаваемом строкой формат если не указана метка_времени. Иначе, по времени, указаному в метке. Подробнее см. в Руководстве.

Графический счетчик

Надписи на странице это конечно хорошо, но есть два момента. Во-первых, необходимо вставлять в страницу PHP код и сохранять ее как .php файл. Во-вторых, где вы сейчас найдете текстовый счетчик? Сплошные картинки. Чтобы не отставать от прогресса, мы тоже сделаем себе такой, благо в PHP входят функции по работе с изображениями. Если вы еще не раскоментировали в php.ini строку "extension=php_gd2.dll" сейчас самое время. Эта строка подключает библиотеку GD2.

В этот раз счетчик должен быть оформлен отдельным файлом:

Файл "gcounter.php"
<?php
  $fname = "cnt".$_GET['id'].".txt";  //Создаем название файла с данными счетчика 

  if (!$fc = fopen($fname, 'r')):     //открываем и загружаем
    $cnt  = 0;
    $date = date('dmY');
    $dcnt = 0;
  else:
    $cnt  = fgets($fc);
    $date = trim(fgets($fc));
    $dcnt = fgets($fc);
  endif;

  $cnt = $cnt + 1;                    //пересчитываем и сохраняем
  if (date('dmY') == $date):
    $dcnt = $dcnt + 1;
  else:
    $dcnt = 1;
    $date = date('dmY');
  endif;

  $fc = @fopen($fname, "w")
    or die('<B>Ошибка при открытии файла для записи.</b>');
  fwrite($fc, $cnt."\r\n");
  fwrite($fc, $date."\r\n");
  fwrite($fc, $dcnt."\r\n");

  while(strlen($cnt) < 5):            //дополняем строку нулями слева
    $cnt = "0".$cnt;                  //зачем? чтобы красиво было :)
  endwhile;

  header("Content-type: image/png");               //сообщаем браузеру, что сейчас пойдет картинка
  if ($im = @imagecreatefrompng("banner1.png")):   //создаем изображение из файла
    $top  = 18;                                     
    $left = 44;
    $w = imagefontwidth(3);
    $w = (5 - strlen($dcnt))*$w;                                  //рассчитываем положение надписей
    $text_color = imagecolorallocate($im, 55, 55, 55);
    imagestring($im, 3, $left, $top, $cnt, $text_color);          //и выводим текст на рисунок
    imagestring($im, 3, $left+$w, $top-12, $dcnt, $text_color);

    imagepng($im);                    //посылаем рисунок браузеру
    imagedestroy($im);                //освобождаем память
  endif;
?>

Как поместить такой счетчик на свою страницу? очень просто:

<IMG src="gcounter.php?id=01">

Все. Если счетчик находится на другом сервере, естественно необходимо указать полный путь. Можно еще сделать из него ссылку, и все будет почти как у "взрослых". Этот счетчик, правда, не собирает сведения о посетителе, но думаю, покопавшись в массиве $_SERVER, можно это исправить. Ну и Топ100 без базы данных сделать затруднительно :).

  • $_GET['id'] - получение из массива $_GET параметра с именем id. В массиве $_GET хранятся параметры, переданые через адрес (метод HTTP GET). Передача параметров таким способом выглядит так: http://www.somesite.ru/page.php?имя1=значение1&имя2=значение2....
  • strlen(строка строка) - возвращает длину строки.
  • header(строка строка) - посылает клиенту заголовок HTTP. Мы использовали его, чтобы сообщить браузеру, что посылаем картинку. В принципе, если обращаться к скрипту только через <IMG src = ...>, можно обойтись и без заголовка, но при обращении напрямую к скрипту, в браузере будет масса странных символов.
  • imagecreatefrompng(строка имя_файла) - загружает картинку в png формате и возвращает дескриптор рисунка. Если загрузка прошла неудачно, возвращает FALSE
  • imagefontwidth(целое шрифт) - возвращает ширину одного символа указаного шрифта.
  • imagecolorallocate(ресурс рисунок, целое красный, целое зеленый, целое синий) - создает новый цвет для рисунка, задаваемый RGB. Функцию необходимо вызвать для каждого цвета, который планируется использовать. Она возвращает номер цвета в палитре рисунка или -1 при возникновении ошибки.
  • imagestring(ресурс рисунок, целое шрифт, целое x, целое y, строка s, целое цвет) - выводит на рисунок строку s заданым шрифтом, начиная с точки с координатами (x, y). Шрифты с номерами 1, 2, 3, 4, 5 - встроеные.
  • imagepng(ресурс рисунок [, строка имя_файла]) - отсылает рисунок браузеру, либо сохраняет его в файл.
  • imagedestroy(ресурс рисунок) - освобождает память, занятую рисунком.

Ну вот, на сегодня это все :)


Вологодский Государственный Педагогический Университет

сделал Р. 'zRrr' Золотов

Рейтинг@Mail.ru