Пишем простейший текстовой счётчик. Простой текстовый счетчик на PHP

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

  1. Прочитать текущее содержимое счетчика;
  2. Увеличить текущее содержимое счетчика на единицу;
  3. Сохранить обновленное содержимое счетчика;
  4. Вывести на печать обновленное значение счетчика.

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

Я сразу приведу PHP-код, реализующий самый простой из всех возможных типов счетчика, а затем уже дам ряд комментариев.

Как видите, скрипт достаточно прозрачный и практически полностью следует сформулированному ранее алгоритму. При этом, для удобства дальнейшей поддержки кода, я в первой же строке определил переменную $file_counter , которую уже и использую. Постарайтесь, по возможности, всегда определять переменные для всех более-менее важных исходных данных и не используйте их напрямую.

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

Для работы с файлами в PHP, как и во многих других языках программирования, предварительно необходимо открыть файл на чтение или запись. Для открытия файла используется функция fopen() , в качестве передаваемых ей параметров мы должны указать путь к файлу и способ доступа ("r" - для чтения, "w" - для записи). В случае успешного открытия файла мы получаем его дескриптор, который далее и используется при любых операциях с файлом.

На следующем шаге, используя функцию fread() , мы читаем содержимое файла. Т.к. у нас это очень простой счетчик, то все содержимое файла и является значением счетчика. Но для того чтобы прочитать содержимое файла, нам необходимо, кроме дескриптора файла, также указать и размер читаемых данных. В случае если файл небольшой, проще всего прочитать его в переменную целиком. А значит, нам необходимо предварительно узнать размер файла в байтах. Это делается при помощи функции filesize() .

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

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

Файл может отсутствовать при первом запуске скрипта, и в этом случае он будет создан автоматически - при первом же сохранении счетчика.

Помогите чайнику, плиз. Я дописываю движок своего сайта, размер которого
растет буквально на глазах. Дело в том, что у меня все скрипты напичканы
всякими проверками. Например "счетчик кол-ва просмотров страницы":

1. проверка существования файла
2. читаем файл
3. проверяем, файл должен содержать только одну строку
4. проверяем, в строке должны быть только цифры
5. увеличиваем счетчик
6. пишем обратно в файл
7. проверяем, записалось ли

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

Вопросы:
1. Возможны ли ситуации, при которых файл счетчика показов страницы
будет потерян (обрезан) в момент записи при сбоях (перегрузках, и т.д.) ?
Хакера в учет не брать.
Проблемы одновременного использования файла двумя
пользователями (чтение-запись) тоже.
2. Возможны ли потери собственных скриптов?
3. На хостере есть архивация. Я понимаю, что это, но не знаю, как
используется эта штука. Можно в двух словах объяснить, какая польза от
этой архивации?
4. Я написал выше пример "замороченного" счетчика, а что Вы думаете об
этих многочисленных проверках?

Заранее благодарю Вас.

Ответ: На моем сайте, ВСЁ сохраняется в одном файле (по поводу подсчета просмотров страниц). Раз в полгода ВСЁ это дело стирается, так как работает ПОСТОЯННО, а значит, является самой уязвимой вещью на сайте. Не вижу в этом ничего плохого, так как сама такая статистика направлена только на одно - выявление самых популярных страниц своего сайта и ПОНИМАНИЯ почему же они самые посещаемые.

Ну и пусть, стираются раз в полгода, я сам стираю этот файл, если не происходят сбои на сервере.

По поводу торможения, могу сказать, что в Google есть функция "эффективность сайта", там все сайты с загрузкой страниц более секунды считаются медленными, когда ЭТО увидел сократил свой объем статистики до 1 часа (было сутки), но все-равно страницы генерируются за 1,5 секунды в среднем.

Выбирать Вам, что Вы хотите иметь статистику по сайту, либо чтобы сайт работал как молния.

Думаю, есть золотая середина, ищите её и все будет хорошо.

По поводу проверок, проверки одной строки, проверки цифр, итд - на это время не расходуется, самый большой расход идёт в ЦИКЛАХ, и в считывании БОЛЬШИХ баз данных, всё остальное работает МОМЕНТАЛЬНО. По поводу архивации - это бред... никто и ничего не архивирует - раз в день скачивайте свои базы из интернета, они всегда будут свежие, ПОЛЕТИТ сервак (всё сотрётся), Вы всегда сможете ВСЁ восстановить. И здесь не важно сохраняется инфа в простых файлах, либо в MySql, вылетает так, что и в первом и втором случае уже ничего не восстановишь, пока не запишешь по новому.

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

    - Файл для хранения ip пользователей (ip.txt)
    - Файл для хранения данных счётчика (counter.txt)
    - Сам файл скрипта (counter.php)
    - Шаблон вывода счётчика (template.html)

Алгоритм работы очень прост:

    - Когда скрипт запускается, он получает ip запустившего его браузера.
    - По ip проверяем, были ли уже запросы от этого браузера или нет.
    - Если не были - добавляем ip в базу и прибавляем по единичке ко всем счётчикам.
    - Если уже были - прибавляем по одному поинту к хитам.
    - Выводим данные счётчика.

Отображать наш счётчик будет:

    - Просмотров всего
    - Просмотров сегодня
    - Уникальных посетителей сегодня

Как видите, в теории всё очень просто. На практике не намного сложнее. Создаём все четыре файла. Текстовые файлы не трогаем - в них будет хозяйничать наш скрипт. Шаблон вывода оставим на потом. Открываем counter.php и приступаем.

# Начало файла counter.php
counter.php
$ip =getenv("REMOTE_ADDR");
#Получаем ip запустившего скрипт компьютера
$date =date(chr(39);d.m.Ychr(39);,time());
#Присваиваем переменной $date текущую дату

#Следующий блок считывает файл с ip адресами
$fo = fopen ("ip.txt", chr(39);rchr(39););
#Открываем файл
flock($fo ,1);
#"Запираем" файл для чтения. Если кто-то ещё захочет прочитать этот файл - его запрос "встанет в очередь"
$data = fread ($fo , filesize("ip.txt"));
#Считываем информацию из файла и присваиваем её переменной $data
flock($fo ,3);
# Разблокируем файл
fclose ($fo );
#Закрываем файл

#Нижеследующий блок повторяет ту же самую процедуру с файлом counter.txt
$f = fopen ("counter.txt", chr(39);rchr(39);chr(39);rchr(39););
flock($f ,1);
$counts = fread ($f , filesize("counter.txt"));
flock($f ,3);
fclose ($f );

List($d ,$total ,$hits ,$hosts )=explode("|",$counts );
# Проходимся по данным счётчика и присваиваем их соответствующим переменным. Алгоритм работы простой - идём до разделителя("|"), присваиваем значение первой переменной из list, идём до следующего разделителя и так далее.

#Проверяем, соответствует ли дата в файле счётчика текущей дате. Если нет - обнуляем файл с ip файлами и некоторые значения счётчика.
if ($d !=$date )
{
$d =$date ;
#Обновляем дату
$hits =0;
#Просмотров сегодня теперь равны нулю
$hosts =0;
#То же самое с уникальными посетителями
$erase =fopen("ip.txt",chr(39);w+chr(39););
#Открываем файл с ключём "w+" - это значит, что данные файла обнуляются и на их место мы записываем новые данные
flock($erase ,2);
#Запираем файл для записи
fputs($erase ,"");
#Записываем в файл "всемирное ничто"
flock($erase ,3);
fclose($erase );
}

#Теперь проверяем, есть ли ip у нас в базе.
if (!stristr($data ,$ip ))
# Если нет
{
$file =fopen("ip.txt",chr(39);achr(39););
flock($file ,2);
fputs($file ,$ip ."rn");
#Записываем новый ip в базу
flock($file ,3);
fclose($file );
$total ++;
$hits ++;
$hosts ++;
#Прибавляем к значениям счётчика по единице
}
else
#Если ip уже есть в базе, прибавляем по единице только хитам
{
$total ++;
$hits ++;
}

#Записываем новые данные счётчика в файл
$wfile =fopen("counter.txt",chr(39);w+chr(39););
flock($wfile ,2);
fputs($wfile ,$d ."|".$total ."|".$hits ."|".$hosts );
#Записываем данные с разделителем ("|"), для удобной сортировки, которую мы проводили выше
flock($wfile ,3);
fclosвыше
flock($wfile ,3);
fclose($wfile );

#Всё, теперь можно выдавать пользователю показатели счётчика
include ("template.html");
?>

Шаблон вывода данных счётчика делается очень просто. Файл template.html выглядит так:

echo <<

[ $total :: $hits :: $hosts ]
#Это и есть сам шаблон вывода.

HTML;
?>
#Конец файла counter.php

Вот и всё, мы написали простой счётчик. Можно сделать небольшое усовершенствование скрипта. К примеру, если вы не хотите, что бы кто-нибудь мог посмотреть ip адреса людей, посетивших сегодня вашу страницу. Для этого надо поместить текстовые файлы в отдельныю папку, в этой же папке создать файл.htaccess и написать в нём всего одну строчку:

Не забудьте поставить разрешение на запись в текстовые файлы и в папку, а так же поменяйте путь к этим файлам в скрипте.
Что бы вывести счётчик на страницу, в нужном месте пометите следующий код:

include(«путь_к_папке_скрипта/counter.php);
?>

На этом разрешите откланяться. Желаю удачи и успехов в постижении нелёгкого дела программиста.




Есть еще вопросы или что-то непонятно - добро пожаловать на наш

Итак, начнем. Для начала давайте определимся, что именно нам надо делать. При клике на ссылку, для подсчета количества кликов, нам надо специальным скриптом засчитать клик, а после предоставить посетителю интересующую его информацию (сделать редирект на нужный файл). В принципе, последовательность (за счет клика и выдача информации) можно поменять местами, однако учтите, что если счетчик используется для подсчета скачиваний файлов, то для того чтобы после скачки файла выполнялся скрипт, потребуется писать специальный скрипт-загрузчик файлов. Зачем вам лишние проблемы? Такой же принцип работы будет и у счетчика посещений. В данном случае, для ускорения загрузки страницы можно обойтись без редиректа, а просто вставить код счетчика в загружаемую страницу.

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


$f =fopen("stat.dat ","a+ ");
flock($f ,LOCK_EX);
$count =fread($f,100);
@$count ++;
ftruncate($f ,0);
fwrite($f ,$count);
fflush($f );
flock($f ,LOCK_UN);
fclose($f );

Да, вы не ошиблись, это и есть весь скрипт. А теперь давайте разберемся, что и как в нем работает.

Первой строчкой кода - $f =fopen("stat.dat ","a+ "); мы открываем файл stat.dat для чтения и записи, связываем его с файловой переменной $f. Именно этот файл будет хранить данные о состоянии счетчика. Для правильной работы советую устанавливать для данного файла права доступа 777 или аналогичные с полным доступом на чтение и запись.

Следующая строчка - flock($f ,LOCK_EX); очень важна для работоспособности скрипта. Что она делает? Она на время работы данного скрипта (или до ее снятия) блокирует доступ к файлу для других скриптов или копии данного. Почему это так важно? Давайте представим ситуацию: в тот момент, когда пользователь1 кликает на ссылку, запускающую скрипт подсчета кликов, по той же ссылке кликает пользователь2, запуская копию того же скрипта. Как вы увидите далее, в зависимости от того, на какой стадии выполнения находится скрипт, запущенный пользователем1, скрипт запущенный пользователем2 и работающий параллельно со своей копией может попросту обнулить счетчик. Эту ошибку допускают практически все начинающие программисты на PHP, создавая подобные счетчики. Теперь, я думаю ясно, зачем нам блокировка доступа к файлу - в данном случае скрипт, запущенный пользователем2 будет ждать пока отработает скрипт, запущенный пользователем1 (не стоит пугаться, что это замедлит загрузку страниц - даже самые медленные серверы выполняют данный скрипт за сотые доли секунды).

С 3-й строчкой кода $count =fread($f ,100); все ясно. В переменную $count считываем значение счетчика.

Теперь нам осталось произвести запись в файл обновленных данных. Для этого нужно предварительно очистить файл ftruncate($f ,0); вот тут и может возникнуть та опасная ситуация с обнулением счетчика, про которую я говорил. Однако мы используем блокировку файла, так что бояться нечего.

Записываем обновленные данные о значении счетчика fwrite($f ,$count );

Для надежности принудительно очищаем буфер ввода/вывода для данного файла fflush($f );

Снимаем блокировку с файла flock($f ,LOCK_UN); на самом деле ее можно не снимать - она автоматически снимается после закрытия файла. Однако для полноты примера я ее все же написал.

Закрытие файла fclose($f ); тоже не обязательная функция т.к. все открытые скриптом файлы, после завершения его работы, автоматически закрываются. Но опять же, для полноты примера... =) кроме того, если на этом скрипт не заканчивается, а работать с файлом более не понадобится, рекомендуется сразу же закрывать файл.

Ну вот и все. Как видите совсем не сложно. Теперь для подсчета количества посещений, просто вставляйте данный код в страницу. А если же вы захотели подсчитать количество скачек какого-то файла, то вставляйте данный код в отдельный PHP файл, ссылку с имени файла заменяем на ссылку на данный скрипт, а в конец скрипта дописываем редирект на файл для скачки. Лучше всего его выполнить на PHP: Header("location:/download_dir/file_to_download.rar ");

Ах да. Надо же еще выводить значение счетчика, иначе считать то зачем =). Значения, разумеется, берем из файла. Можно сделать как в примере самого счетчика:

$f =fopen("stat.dat ","a+ ");
flock($f ,LOCK_EX);
$count =fread($f ,100);
flock($f ,LOCK_UN);
fclose($f );

Echo "Количество скачек/кликов: $count ";