С помощью php рисуем простой график посещений сайта В последнее время PHP набирает все большую популярность. Только за последние две недели 5 сайтов моих знакомых перекочевали на «Холм» с «Народа, так как на этом новом хостинге вовсю можно использовать скрипты, да и сам работает быстрее (пока). Кстати сказать, ребята на Холме тоже не сидели сложа руки и, видя прибывающий народ, сделали подарок, сняв ограничения на хранение файлов на сервере даже в «бесплатном» варианте. Для начинающих сайтостроителей началась счастливая пора. По предыдущим номерам VR, думаю, вы уже научились шаблонизировать сайты, создавать простые счетчики посещений, делать страницы динамическими и т.д. Как, еще нет? Тогда бегом качать прошлые выпуски! А сегодня я собираюсь рассказать о построении графика посещений в вашем творении. Причем делать это мы будем не через JAVA апплеты и графические библиотеки, а рисовать прямо символами, раскрашенными в разные цвета. В итоге должно получиться нечто, похожее на вот этот рисунок. График состоит повторяющегося символа восклицательного знака, с уменьшенным промежутком между буквами. По нему можно легко увидеть количество пришедших человек в какой-то конкретный день, а так же оценить посещаемость в целом за месяц. Конечно, нарисованный на flash или созданный в реальном времени на сервере рисунок выглядел бы лучше, не так дискретно, но сделать такое не так-то просто. Ограничимся пока символьным представлением, тем более графика в браузерах включена не у всех пользователей Интернета, не говоря уже о flash, а это творение должно отображаться везде. Кстати, символьные рисунки сейчас в моде, в последнее время появляются даже специальные программы для ASCII art, что ж, давайте и мы что-нибудь напишем... Итак, что-то я разрекламировался, пора уже приступить к созданию. Сначала составим некоторый алгоритм, по которому будет работать будущий скрипт. Традиционно, начинающие сайтостроители счетчики делают довольно просто, записывая в некоторый файл и считывая оттуда число, постоянно увеличивающееся на 1 при каждом обращении к сайту. Сейчас нам такой способ не подходит, ведь мы должны сосчитать именно разных посетителей, а значит количество разных IP адресов. Это во-первых. Во-вторых, при прохождении суток, мы должны каким-либо образом разграничивать записи, для осуществления подсчета в определенный день. Я предложу это сделать созданием каждый раз нового файла, с именем текущего числа. Но тогда, скажете вы, по прошествии нескольких месяцев на сервере образуется большая куча файлов, разобраться в которой будет нелегко! Правильно. Чтоб этого не случилось, сделаем разграничение и на месяцы, поместив соответствующие файлы в отдельные каталоги. И в-третьих, нам нужно все это добро сосчитать, обработать и красиво вывести, что, тоже не просто. Приступим. Итак, привожу часть кода: ‹font size=1 color="0000FF"; style="line-height:130%;letter-spacing:1pt;"> График посещаемости: ‹br> ‹/font> ‹? chdir("schet"); If (!file_exists(date("M Y"))) {mkdir(date("M Y"),0755);} chdir(date("M Y")); $File = date("d").".txt"; $Myfile=Fopen($File,"a+"); flock($Myfile,LOCK_EX); $ip =getenv("REMOTE_ADDR"); // $ip = getenv("HTTP_X_FORWARDED_FOR"); Fwrite($Myfile,$ip."r"."n"); fflush($Myfile); flock($Myfile,LOCK_UN); Fclose($Myfile); chdir(".."); Я надеюсь, что мой читатель имеет представление о PHP и программировал хоть что-либо на этом замечательном языке, поэтому каждую запятую комментировать не буду. Сначала у меня идет вообще HTML-код, чтоб он не мешался на главной странице при ее проектировке, я решил занести его сюда. Там я выставляю уже упомянутый уменьшенный промежуток между символами. Думаю, что для порядка наш счетчик должен находиться в своей папке, я назвал ее «schet». Итак, заходим в нее функцией chdir("schet"). Затем я проверяю существование каталога текущего месяца (помните, о чем мы говорили?) и, в случае надобности создаю его. Вообще, в имени файла допустимо писать путь, и теоретически вместо chdir(date("M Y")); $File = date("d").".txt"; можно бы было написать $File = date("M Y")."/".date("d").".txt"; Когда я писал скрипт, я изначально так и сделал, и в моем виндовском апаче все работало. Но закачав страницу на сервер, обнаружил, что счетчик не работает, не может считать информацию и выводит пустой график. Каково же было мое удивление, когда, зайдя по ftp на сервер, я увидел файлы, с именами типа «Aug 2004/28.txt», «Aug 2004/30.txt» и так далее… Все они лежали в директории «schet». Total Commander, который используется мной в качестве файлового менеджера, даже отказался корректно их отображать, и, мало того, не смог удалить эти файлы… Не знаю, что за OS стоит на «Холме», но во избежание подобных проблем советую использовать функцию chdir для прохода в каталог и выхода из него, отказавшись от ввода пути в самом имени файла при открытии. Хотя есть и альтернативный вариант, с использованием константы DIRECTORY_SEPARATOR. В ней содержится то, чем каталоги разделяются. Например, так $File = date("M Y"). DIRECTORY_SEPARATOR.date("d").".txt"; Далее идет стандартная схема открытия файла с дозаписью, получение IP пользователя и занесения его в файл. Обращу лишь внимание на установку блокировки flock($Myfile,LOCK_EX); Она нужна при большой посещаемости сайта, для предотвращения обнуления счетчика, когда возможно одновременное обращение к одному и тому же файлу. Так же вы можете видеть закомментированную строку. Это альтернативный метод получения IP. Если вы используете хостинг «Холм», то там рекомендуется применять именно переменную "HTTP_X_FORWARDED_FOR", так как “REMOTE_ADDR" почему-то выдает ошибочные значения (эх, бесплатный хостинг). На самом деле в HTTP_X_FORWARDED_FOR прокси-сервер пишет оригинальный адрес. И лучше проверять, если установлен HTTP_X_FORWARDED_FOR, то использовать его, иначе — REMOTE_ADDR. Для верности лучше проверять не только на пустоту, но и на похожесть с помощью ereg('([0-9]{1,3}.){4}',$ip.'.'). Ну вот и все в этой части. Нет, рано, рано расслабляться, нам предстоит еще большая работа! Построение графика только начинается! Вот, читайте дальше: If (!file_exists(date("M Y"))) {mkdir(date("M Y"),0755);} // Создаем каталог(на всякий случай, а вдруг нету chdir(date("M Y")); // и заходим туда $i=0; //Обнуляем переменные, как говорит Задорнов, так, "на всякий случай" //замечу, что в ней хранится число обрабатываемой сейчас строки while($i‹31) // запускаю глобальный цикл перебора файлов { $i++; // увеличиваю на 1 If ($i‹=9) {$File="0".$i.".txt";} else {$File=$i.".txt";} /* создаю имя файла, причем т.к. имена файлов у нас вида «07.txt» и «15.txt», то при значении «i» меньше 9, надо дописывать вперед «0» */ $Different = 0; If (file_exists($File)) // если файл существует, то считаю посетителей { $mass = File($File); // читаю файл в массив $Different = count(array_flip($mass)); /* на мой взгляд, самый легкий способ посчитать разных посетителей. Массив переворачивается, одинаковые IP уничтожаются и остаются в 1 экземпляре. Например, пусть массив будет вида $M=array("1"=>"aaa", "2"=>"aaa", "3"=>"ccc"); $M=array_flip($M); // теперь $M===array("aaa"=>"2", "ccc"=>"3"); И функция «count» с легкостью выдает количество записей в массиве $mass, равное количеству разных посетителей. На мой взгляд, такая конструкция проще, чем запускать циклы перебора и сравнения. */ } $itogmass[$i] = $Different; /* вот, по завершению цикла массив $itogmass будет содержать в себе количество разных посетителей на каждый день. Подмечаю, что если скрипт запущен, например, 14 числа, то следующие 16 элементов массива будут содержать нули. Далее приступаем к начертанию графика. Я сделал его гибким, чтобы легко и без искривлений можно было менять его размеры. */ } $visota = 8; // задается нужная высота $dlina = 60; // задается нужная длина $kofvisota = $visota/max($itogmass); $kofdlina = $dlina/count($itogmass); //считаем коэффициенты $kofcv = 170/$visota; for($i=$visota; $i>=0; $i--)// запускаю цикл построения графика { echo "‹font color=4B0082 size=2>‹b>"; // устанавливаю шрифт If (($i==$visota) and (max($itogmass) ‹ 10 )) {echo max($itogmass);} else /* тут я немного схалтурил. По идее, строка должна выводить максимальное число людей за месяц, но если оно больше 9, то число состоит более, чем из 1 символа, что приводит к перекосу графика, и я урезал ее работоспособность до 9. Если на вашем сайте посещаемость больше (тогда я вообще не понимаю, зачем вы тратите время, читая эту ерундистику, то исправьте код сами . Подсказка: вам поможет функция str_pad, которая может дополнять строку нужными символами. */ {If ($i==round($visota/2)) {echo (round(max($itogmass)/2));} else {If ($i==0) {echo "0";} else echo "_";}} /* если выводить количество людей в каждой строчке, то из-за уменьшенного строчного интервала цифры сольются и станут нечитаемыми, поэтому выводим только сверху и посередине. Перед остальными же строчками ставим просто «_» */ echo "‹/b>‹/font>"; // завершаем расставлять цифры с пропусками $rez = -1; for($j=1; $j‹$dlina; $j++) Дальше идет цикл раскраски { If ( round ($j/$kofdlina) != 0) $znach = round($itogmass[round($j/$kofdlina)]*$kofvisota); else $znach=0; $cv = dechex(190-round($i*$kofcv)); // для градиентных цветов $cv2 = dechex(round($i*$kofcv)); // для градиентных цветов $cv = str_pad($cv,2,'0',STR_PAD_LEFT); // если 1 символ, приписываем впереди 0 $cv2 = str_pad($cv2,2,'0',STR_PAD_LEFT); If (($znach>=$i) and ($rez!=1)) {echo ('‹/font>‹font color="FF'.$cv.'00">');} If (($znach‹$i) and ($rez!=0)) {echo ('‹/font>‹font color="00'.$cv2.'FF">');} If ($znach>=$i) {$rez=1;} else {$rez=0;} echo "!"; // начинаем расставлять ! } echo "‹br>"; } ?> Этот алгоритм не указывает цвет для каждого символа, он устанавливает новый цвет только в том случае, если натыкается на смену цвета, т.е. на столбец графика. Посмотрев на код, вы можете спросить, зачем так сложно? Можно бы было перед каждым символом писать теги его цвета и все… Но тогда размер вашей странички неумолимо увеличился бы, а это не есть хорошо… Один только этот график весил бы под сотню килобайт, не говоря о другом содержании. Но если заставить нашу программу писать теги смены цвета только когда это действительно нужно, размер значительно уменьшится. Ну а дальше совсем просто, осталось только вывести стандартную статистику. Для подсчета всех обращений к сайту я использую простую, стандартную схему, где число, записанное в файле, увеличивается на 1. Для вывода посетителей на сегодняшний день опять применяю уже знакомый переворот массива ‹font size=2 color="0000FF"; style="line-height:100%;letter-spacing:7pt;" > месяц>> ‹/font> ‹font size=1 color="00008B"; style="line-height:100%;letter-spacing:1pt;" > ‹? chdir(".."); If (!file_exists(date("M Y"))) {mkdir(date("M Y"),0755);} chdir(date("M Y")); $File = date("d").".txt"; $mass = File($File); chdir(".."); echo "Статистика на сегодня: "; echo "Обращений к сайту: ".count($mass)."‹br>"; echo "Посетителей сегодня: ".count(array_flip($mass))."‹br>"; // снова переворот $f=fopen("counter.dat","a+"); // стандартная схема счетчика flock($f,LOCK_EX); $count=fread($f,100); @$count=$count+1; ftruncate($f,0); fwrite($f,$count); fflush($f); flock($f,LOCK_UN); fclose($f); echo "Всего обращений: ".$count."‹br>"; chdir(".."); // не забывайте про это ?> ‹/font>
|