Учимся считать?

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

Считаем посещения


Как всегда, для работы нам понадобится сервер (например, Apache) с установленным гипертекстовым препроцессором РНР, текстовый редактор и немного времени. Для начала давайте разберемся более подробно с поставленной задачей. Есть несколько страниц сайта. Все они, конечно, имеют уникальный адрес — URL. Вот его-то мы и положим в основу нашей базы данных. Для этих целей отведем один файл с именем, например, urlfile.txt. Вторая составляющая статистики — это количество посещений. Мы не будем пока касаться вопроса уникальности каждого захода, а реализуем для начала простой подсчет посещений. Для статистики отведем еще один файл — counter.txt (жалко, что ли?.. :-). Сам скрипт разместим в файле log.phtml, а вывод результатов — в файле index.phtml. Все четыре файла полезно вынести в отдельную директорию, чтобы в дальнейшем не запутаться. Она у нас будет названа count. Не забывайте, что на файлы, в которые будет осуществляться запись (у нас их два — с расширением .txt), нужно установить соответствующие атрибуты, разрешающие в них запись, иначе скрипт выдаст ошибку.
Когда все готово, можно начать программировать. В первую очередь сделаем файл log.phtml, как самый главный. Открываем свежесозданный файл в текстовом редакторе (можно и в блокноте) и прописываем туда следующие строки:

<?
if($QUERY_STRING != "")
{ $url = $PHP_SELF.'?'.$QUERY_STRING; }
else { $url = $PHP_SELF; }

Этим кодом мы считываем адрес, с которого вызывается скрипт. Этот адрес прописан в переменной окружения $PHP_SELF, но нужно учитывать, что в адрес вполне могут быть включены параметры, которые идут после вопросительного знака, и считать их можно уже из переменной окружения $QUERY_STRING. Итак, если эта переменная у нас пуста, адрес считывается из $PHP_SELF, если нет, адрес комбинируется из двух переменных окружения.

$add = $DOCUMENT_ROOT."/count/urlfile.txt";
$adds = $DOCUMENT_ROOT."/count/counter.txt";
$li = file($add);
$a = count($li);

Здесь мы формируем пути, по которым скрипт будет искать файла для записи данных статистики. $DOCUMENT_ROOT — тоже переменная окружения, и в ней хранится абсолютный путь (адрес) к Вашему сайту. Благодаря наличию данной переменной обеспечивается стопроцентная работоспособность скрипта, из какой бы директории он ни был запущен. 
В конце этого кода считываем в массив с именем $li содержимое файла с базой данных адресов. Пока эта база пуста, и массив соответственно пуст. 

$i = 0; $w = -1;
while ($i <= $a):
$tmp = trim(str_replace ("\n","", $li[$i]));
if ($tmp == $url) { $w = $i; $i = $a++; } 
$i++;
endwhile;

Этот код отвечает за определение местоположения запрошенного адреса в массиве адресов. Так как пока этот массив пуст, то запрошенный адрес не обнаруживается и его необходимо туда записать. За это отвечает следующий код:

if ($w == -1)
{ $fp = fopen($add, "a+"); if ($fp) { $fw = fwrite($fp, $url."\n"); fclose($fp); } 
$fp = fopen($adds, "a+"); if ($fp) { $fw = fwrite($fp, "0"."\n"); fclose($fp); } 
$w = $a++; }

Файл адресов и файл количества посещений дополняются новыми данными, учитывается и перевод строки, так как он является разделителем при считывании файла в массив в дальнейшем. Если же запрошенный адрес уже есть в базе данных, этот код не выполняется, так как переменная $w равна номеру позиции запрошенного адреса в массиве адресов. Таким образом, достигается равновесие — если адрес есть, то хорошо, если нет — его туда добавляют, а переменная $w все равно указывает на номер позиции в массиве адресов. В любом случае идем дальше:

$co = file($adds);
$co[$w] = trim(str_replace ("\n","", $co[$w]));
$co[$w]++; $count = $co[$w];
$co[$w] = $co[$w]."\n";

Этот кусочек кода отвечает за загрузку базы данных количества посещений страниц в массив $co и за увеличение на единицу нужной позиции в этом массиве. В переменную $count кладется значение текущего счетчика посещений данной страницы, его можно позже вывести на экран. 
Отдельно стоит рассмотреть вторую строчку, так как она нам уже встречалась. Дело в том, что когда РНР считывает данные из файла в массив, разделителем считается перевод строки. Но это не значит, что он не попадает в массив. Кроме перевода строки, в массив могут попасть пробелы с начала и с конца строки, и от них, равно как и от перевода строки, нужно избавиться. Именно это и делает указанная строчка кода. А дальше — увеличиваем показание счетчика, дополняем его переводом строки для корректной записи, и…

$p=implode("", $co);
$fp = fopen($adds, "w"); 
if ($fp) { $fw = fwrite($fp, $p); fclose($fp); }

…записываем весь массив $co в файл. Прежде, чем записать, массив склеивается в одну переменную, и уже она легко записывается. Осталось завершить код тегом окончания кода РНР:

?>

Вот и все, что требовалось записать в самый большой и сложный :-) файл log.phtml. Хочу Вас обрадовать — дальше будет проще. Как я и обещал, мы сделаем вывод результатов на экран, чтобы была возможность наглядно оценить посещаемость тех или иных Ваших страниц. За это, как Вы помните, у нас отвечает файл index.phtml. Начнем теперь заполнять кодом его:

<? include ($DOCUMENT_ROOT."/count/log.phtml"); ?>

Вот так, кстати, будет вызываться наш скрипт статистики. Подобная вставка вызовет либо пополнение базы данных адресов, либо увеличение соответствующей позиции счетчика на единицу. Мы могли бы и не учитывать в рейтинге страницу результатов, но никто нам этого не запрещает. А сами результаты не плохо бы разместить в таблице:

<table align="center" border="1">
<?
$add = $DOCUMENT_ROOT."/count/urlfile.txt";
$adds = $DOCUMENT_ROOT."/count/counter.txt";
$li = file($add);
$co = file($adds); 
$a = count($li); 
Ну, эта часть нам уже до боли знакома. Блок кода практически ничем не отличается от такого же блока в файле log.phtml. Мы узнали адреса файлов базы данных и ввели информацию в массивы. Осталось ее только вывести, предварительно отформатировав тегами HTML:

$i = 0; $w = 0;
while ($i < $a):
echo "<tr><td>
<a href=$li[$i]>$li[$i]</a>
</td><td>$co[$i]</td></tr>";
$i++; 
endwhile;
?></table>

Теперь наши результаты будут выведены в таблице в виде адрес — количество посещений. Вот и вся работа! В заключение хочу еще раз напомнить, что вызов скрипта статистики осуществляется следующей командой:

<? include ($DOCUMENT_ROOT."/count/log.phtml"); ?>

Достаточно вставить этот код в любое место любого файла (но только с расширением для РНР!) — и он будет проиндексирован в базе данных, и в дальнейшем каждое его посещение будет учитываться. Если Вас интересует пример — посмотрите, как работает подобный скрипт на сайте http://virtual.bresttelecom.by/.  Удачных Вам подсчетов!

Что такое cookie
Ну, допустим, считать своих посетителей мы научились. А как сделать счетчик персонального учета посещаемости? Так, чтобы вывести посетителю информацию о том, сколько раз он заходил на Вашу страничку. 
Эта задача несколько иного рода, но решается она на самом деле еще проще. Но сначала нам придется познакомиться с одной очень полезной и важной штукой. Я имею в виду технологию cookie. Переводится на русский это английское слово примерно так — печенье, кусочек. В данном случае имеется в виду кусочек информации, записанной сервером на компьютер посетителя. В дальнейшем эту информацию можно извлечь, причем сделать это может только тот сервер, который записал ее туда. Информация ограничена размером 4 килобайта. Есть ограничения по времени существования cookie, по их количеству и т.д. Бояться этой технологии не нужно, и многие сайты очень активно используют ее для сбора информации о своих клиентах, их предпочтениях, настройках и т.д. Для примера представьте себе форум, в котором нужно обязательно указывать имя, адрес или другую информацию. Обычно все это приходится каждый раз вводить заново, а с помощью cookie все данные можно запомнить на компьютере клиента и при следующем посещении форума их извлечь и воспроизвести в форме. Еще проще — один раз запомнить имя посетителя, и каждый раз приветствовать его по имени.
Самый простой способ установить cookie с помощью РНР — это использовать специальный оператор:

setcookie('name', '12345');

Теперь, пока не будет закрыто окно браузера пользователем, переменную $name со значением равным числу 12345 можно считать с помощью другого оператора:

isset ($name);

Часто делают сразу проверку, установлена или нет соответствующая переменная, и на основе полученных результатов принимают решение, что делать дальше:

If (isset ($name)) { … установлена … } else { … нет … }

Надо помнить, что установленный таким образом cookie живет только до тех пор, пока не закрыто окно браузера, его породившее. 
Как только пользователь закрывает окно, установленная переменная уже не доступна. Это так называемый сессионный cookie. Впрочем, совсем не сложно продлить срок жизни cookie до нужного времени. Делается это с помощью третьего параметра оператора setcookie, который указывает дату истечения срока действия cookie либо срок его действия, если число меньше, чем дата установки:

$y = mktime(0,0,0,1,1,2002);
setcookie('name', 'bret', $y);

Перед тем, как задать третий параметр, его нужно сформировать специальной функцией. Дело в том, что в РНР этот параметр указывает на количество секунд, прошедшее после 1 января 1970 года. Немного странно, но уж как есть. Функция mktime() именно для этого и предназначена. Ей нужно указать час, минуту, секунду, месяц, день и год в такой же последовательности. На выходе получим нужное значение в секундах, прошедших с 1.01.1970. В примере cookie будет жизнеспособен (а значит, и поддастся считыванию) до 1 января 2002 года.
Переустановить или удалить cookie очень просто — достаточно указать либо новое значение, либо не указать его вовсе. И под конец одно существенное ограничение. В силу каких-то пока не очень понятных мне свойств работа с cookie должна вестись до какого-либо вывода на экран (в браузер пользователя) любого текста, в том числе и тегов HTML. То есть вот так уже не сработает:

<html>
… работаем с cookie …

Только так:

… работаем с cookie …
<html>
… любые другие теги и текст …

Запомните это ограничение и старайтесь подстраиваться под него, так как тут ничего поделать нельзя. Это не РНР виноват, так уж устроены эти самые cookie. Вот теперь пришла пора от теории перейти к практике. 

Персональный счетчик
Вооружившись такими знаниями, последим за своими посетителями на примере персонального счетчика. В первых строчках файла, еще до вывода любых тегов и сообщений, пишем:

<?
$y = mktime(0,0,0,1,1,2022);
if (isset ($name)) { setcookie('name ', '0', $y); }
else { $name++; setcookie('name ', $name, $y); }
?>

Смысл кода очень прост. Если cookie с именем name установлен, его значение считывается и увеличивается на единицу. Если нет — записывается в cookie ноль. В дальнейшем он будет считан и учтен. В любом месте страницы теперь можно вывести результаты:

<p>Персональный счетчик — <? Echo $name; ?></p>

Как видите, еще проще — весь код буквально уместился в одну строчку. Теперь вы легко сможете организовать с помощью технологии cookie много полезных приемов. 
Только не забывайте, что некоторые Ваши посетители могут запрещать браузеру принимать cookie, нужно позаботиться и о них. 
На крайний случай — просто предупреждать о необходимости разрешить их прием.