CFA LogoCFA Logo Computer
Новости Статьи Магазин Драйвера Контакты
Новости
RSS канал новостей
В конце марта компания ASRock анонсировала фирменную линейку графических ускорителей Phantom Gaming. ...
Компания Huawei продолжает заниматься расширением фирменной линейки смартфонов Y Series. Очередное ...
Компания Antec в своем очередном пресс-релизе анонсировала поставки фирменной серии блоков питания ...
Компания Thermalright отчиталась о готовности нового высокопроизводительного процессорного кулера ...
Компания Biostar сообщает в официальном пресс-релизе о готовности флагманской материнской платы ...
Самое интересное
Программаторы 25 SPI FLASH Адаптеры Optibay HDD Caddy Драйвера nVidia GeForce Драйвера AMD Radeon HD Игры на DVD Сравнение видеокарт Сравнение процессоров

АРХИВ СТАТЕЙ ЖУРНАЛА «МОЙ КОМПЬЮТЕР» ЗА 2003 ГОД

ПеРсоНальный опРос

Дмитрий СВИРЕПЧУК

На этой странице речь пойдет о web-программировании. Не надо переворачивать страницу! Даже если ты и не программист, тебе может понравиться. Сделаем полезную программу (скрипт) для твоего сайта. Это будет программа опроса посетителей. Пользователь заполнит маленькую формочку, а также сможет увидеть результаты голосования. А суть нашего будущего скрипта как раз и будет заключаться в том, как выводится результат. Заинтриговал? Читай дальше.

Что нам нужно?

Начинаем работу. Писать будем на РНР (Personal Home Page — см. цикл Артема Шманцырева «Сервер племени апачей»). Давай сначала более конкретно разберем поставленную перед нами задачу.

Нам нужно поместить на страницу небольшую форму, которая будет представлять собой набор переключателей и кнопку submit.

Предположим, мы срочно хотим узнать от посетителей, какой сорт колбасы им нравится больше всего. Предоставим им на выбор четыре: «Докторская», «Салями», «Кровянка», «Ливерная».

Что нужно нашему скрипту для работы? Во-первых, ему нужно где-то хранить результаты опроса. Где? Нет, холодильник для этого не подойдет. Мы будем хранить результаты в файле. А назовем его stat.dat. Его структура крайне проста: четыре строчки, в каждой из которых будет записана цифра. Эта цифра и есть количество голосов, отданных за каждый из вариантов ответа.

Далее следует заметить, что мы делаем честную систему опроса, а не что-то там в духе судейства на футбольном чемпионате. Поэтому следует сделать так, чтобы один и тот же посетитель не мог проголосовать дважды. К сожалению, мы не можем проследить за каждым интернет-пользователем (уж очень их много). Зато мы можем проконтролировать, чтобы один посетитель не отдавал свой голос два раза подряд. Как? Ты должен знать, что у каждого путешествующего по сети есть свой IP-адрес. Из своего скрипта мы будем его получать и сравнивать с IP-адресом предыдущего зашедшего на страницу. Если они совпадут, то голос не засчитается. Естественно, нам нужно где-то хранить тот самый «IP-адрес предыдущего зашедшего на страницу». Его будем хранить… Да нет же! Не в холодильнике — в файле! Этот файл назовем lastip.dat. Он должен размещаться в той же директории, что и stat.dat. Его структура будет еще проще, чем у предыдущего файла. Он будет состоять из одной строчки: в ней и будет записан IP-адрес. Какие же действия будет выполнять наш скрипт? А вот какие:

получить информацию, за какой вариант отдан голос;

увеличить общее количество голосов за этот вариант на единицу;

сохранить изменения в файле stat.dat;

вывести результат.

А? А-а! Руки от нетерпения чешутся? Хочешь узнать, как будет выводиться результат? Он будет выводиться в виде .jpeg-картинки. Чего руки распустил? Ты дослушай сперва. Эта самая картинка будет генерироваться скриптом автоматически, а выглядеть будет столбиковой диаграммой (она же гистограмма) процентного соотношения голосов. Еще на каждом столбике будет подписано, сколько процентов голосов было отдано за этот вариант ответа. Где-то в сторонке подпишем общее количество проголосовавших... Мне тоже понравилось, когда придумал.

Практическая и умеющая считать

Еще нам необходимы сами файлы скрипта. Их будет два: первый — для сбора статистики и изменения файлов, а второй будет собственно рисовать. Сразу отвечу на пока еще не заданный вопрос: почему нельзя объединить обе части в один файл? Все просто. Как правило, для того чтобы собрать статистику, выделяется отдельная страница с формой, а результаты (еще и в виде баннера) иногда хочется разместить на нескольких (а то и на всех) страницах сайта. Именно для этого мы их и разделили. Первая часть скрипта — та, которая обрабатывает данные, переданные формой, будет находиться в файле stat.php. Код второй части, той, что будет рисовать изображение, должен находиться в файле draw.php. Открывай первый файл своим любимым текстовым редактором (лучше всего notepad) и записывай в него такой текст:

Такими символами мы сообщаем интерпретатору, что начался код РНР.

Функция file() берет в качестве аргумента имя текстового файла и возвращает его содержимое в виде массива. Причем каждая строчка файла записывается в отдельный элемент массива.

Теперь нулевой элемент $lastip содержит тот самый последний IP-адрес. Элементы 0, 1, 2 и 3 массива $stat, соответственно, содержат количество проголосовавших за все сорта колбасы.

А вот тут уже начинается самое интересное. Это, как видишь, условный оператор. Я думаю, ты уже знаешь, как с ним обращаться, но видно, мне следует пояснить, что за условие он проверяет. Если все условие в целом (а оно состоит из двух подусловий) верно, то тогда мы начинаем выполнять основную часть программы — пересчитываем голоса и сохраняем в файлах новые значения. Если же условие ложно, то тогда происходит только переадресация на другую страницу. Зачем она нужна, объясню, когда непосредственно до нее доберемся.

Сначала мы вызываем функцию IsSet() и передаем ей в качестве параметра переменную $mark. Что? Да, раньше она не использовалась. И нигде не определялась. Эта переменная передается скрипту из формы. Просто саму форму я еще тебе не показывал. $mark может принимать четыре значения: от нуля до трех, для каждого сорта колбасы. Функция IsSet() проверяет, установлена ли переменная, которая передана ей аргументом. Если переменная установлена, то возвращается значение true, в противном случае —false. Такая проверка необходима в том случае, если наш скрипт был случайно (или специально) запущен без параметров. В таком случае мы не должны ничего делать.

Следующее подусловие trim($lastip[0])!=$REMOTE_ADDR проверяет, не совпадает ли IP-адрес текущего посетителя с IP-адресом предыдущего. Поясняю, как это делается. Переменная $REMOTE_ADDR (обрати внимание на регистр букв) — это переменная окружения. Она автоматически передается программе. Есть еще несколько таких переменных, но они нас не касаются. В $REMOTE_ADDR хранится IP-адрес пользователя, который вызвал скрипт. А с чем же сравнивается значение? С адресом, который был загружен из файла. Только он еще и передан функции trim(), которая удаляет все ведущие и конечные пробельные символы. Под пробельными символами я подразумеваю табуляцию, собственно пробелы, знаки перевода строки и нового абзаца. Зачем нужно нам все это вырезать? А вдруг они как-то прицепились! Такая проверка никогда не мешает. Обрати также внимание на сам процесс проверки на неравенство. Именно неравенство — нам нужно, чтобы в случае совпадения скрипт просто переадресовывал вызов. Символ выглядит так: !=. Восклицательный знак означает логическое «НЕ».

В конечном счете, если оба подусловия примут значение «истина», программа будет выполняться дальше, без пропусков.

фигурная скобка выделяет те операторы, которые должны быть выполнены внутри тела if. Если фигурную скобку пропустить, тогда выполнится только одна следующая строчка.

Теперь в массиве $stat хранится количество голосов за каждый вариант.

Увеличиваем на единицу количество голосов за тот вариант, за который отдал свой голос посетитель. Обрати внимание, как мы проводим увеличение. Если пользователь проголосовал за вариант «3», то тогда увеличивается именно этот элемент массива $stat, ведь в нем и хранится количество проголосовавших за вариант «3».

Здесь мы считаем сумму всех голосов и заносим ее в переменную $suma. Она нам понадобится в будущем.

Ну вот и понадобилась! Эти четыре переменные будут содержать процентную долю голосов, отданных за каждый вариант от общего числа этих самых голосов. Как видишь, мы еще и округляем вычисленное значение при помощи функции round(). Зачем? Представь себе, что на нашем рисуночке размером с баннер будет изображено такое число: 43.124587269456. Оно засорит рисунок, а пользователю такая точность опроса вовсе не нужна. Я думаю, мне стоит сказать еще два слова о функции round(). Она просто работает по законам математики. То есть возвращает число, ближайшее к аргументу.

Цикл со счетчиком… Я думаю, понятно, как он работает. Мы просто берем и «зачищаем» все элементы массива $stat путем удаления лишних пробельных символов.

Функция fopen предназначена для открытия файлов. Она получает на входе имя файла, который нужно открыть, и режим, в котором его открывают; возвращает функция дескриптор файла. В нашем случае мы открываем файл stat.dat в режиме wt. Буква tозначает, что мы хотим работать с текстовым файлом. Всегда добавляй этот символ в конце, если работаешь с текстом, иначе интерпретатор решит, что ты пытаешься открыть бинарный файл (картинку, например). А хочешь знать, что означает буква w? Это значит, что наш файл будет создан чистым (если его не существует) или же перезаписан (если такой файл уже есть). Да, есть еще режимы открытия. Вот они:

r — файл открывается только для чтения;

·r+ — файл открывается как на чтение, так и на запись. Если файла такого нет, возвращается false;

w+ — делает то же самое, что и предыдущий, но если файла не существует, создает его заново;

a — открывает файл на чтение и запись, но в отличие от всех предыдущих режимов, курсор тут же переходит в конец файла. Полезно в том случае, если надо что-то дописать в уже существующий файл. Если файла с таким именем нет, то возвращается значение false.

a+ — аналогичен простому а, только в случае отсутствия необходимого файла таковой создается, и курсор становится на его начало.

В случае удачного открытия, как уже упоминалось, функция fopen() вернет дескриптор. Это будет целое число, через которое все функции будут выполнять действия с файлом, который привязан к этому дескриптору.

Теперь нужно заблокировать файл от записи другими копиями скрипта. В противном случае (если в файл начнут писать несколько процессов сразу) возможна полная потеря данных… Короче, обнулится твой счетчик.

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

LOCK_SH (можно заменить просто на цифру 1). Это разделяемая блокировка. Суть ее заключается в том, что если кто-то захочет прочитать данные из файла, то его «пропустят». Но все же это произойдет только в том случае, если программа не записывает ничего в файл именно в данный момент;

LOCK_EX (или просто 2). Исключительная блокировка. Состоит в том, что никого к файлу не пустят до тех пор, пока он не будет разблокирован;

LOCK_UN (или 3). Снять блокировку. No comments;

LOCK_NB (4). Эта константа является необязательной, но все же она несет смысловую нагрузку. Дело в том, что если скрипт хочет что-то сделать с файлом, но видит, что «кто-то висит на хвосте», в смысле, файл заблокирован другой копией, тогда он останавливается и ждет, пока файл не освободят. Когда же последний становится незанятым, тогда происходит процесс записи/чтения. Но такой подход не всегда правилен. Если тебе нужно работать по такому принципу: «Занят? Ладно, ну его…» то тогда добавь LOCK_NB, и скрипт, увидев заблокированный файл, пойдет выполняться дальше.

Здесь происходит построчная запись количества голосов в файл. Функция fwrite() должна получить дескриптор файла, в который ей надо записать и собственно то, что ей надо записать.

Ну вот, я тебя снова обманул… На самом деле запись производится не сразу в файл, а во временный буфер. Функция fflush() сбрасывает все изменения непосредственно на винчестер. Единственный параметр, который ей надо передать — это дескриптор файла, который требуется сохранить.

Здесь мы снимаем блокировку с файла.

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

Это я объяснять подробно не буду, так как все функции нам знакомы. Опишу лишь общее назначение этого фрагмента кода. Здесь мы записываем в файл lastip.dat IP-адрес посетителя. При следующем запуске скрипта этот адрес будет расценен как «предыдущий».

Это закрывающая скобка от if’а, который был в самом начале.

Эта функция выполнится в любом случае, так как стоит уже вне блока if. Вообще, функция Header() предназначена для вывода заголовков HTTP. В данном случае мы хотим перенаправить браузер пользователя на страницу, с которой он был запущен. Тут могут быт два вопроса: Зачем это надо? Что такое $HTTP_REFERER? Ответ первый: поскольку наш скрипт сам ничего не выводит в браузер, пользователю будет неприятно набирать заново что-то в адресной строке; он может растеряться, испугаться и убежать. Ответ второй: $HTTP_REFERER — это еще одна переменная окружения. Она содержит URL страницы, с которой был запущен скрипт. Никогда не используйте функцию вывода заголовков после того, как что-то уже выводилось в браузер. Иначе последует уведомление об ошибке и ничего больше. Что поделать, так уж устроен протокол HTTP, что все заголовки должны идти перед всем остальным.

Этим мы уведомляем интерпретатор о том, что код PHP закончился.

Настала пора создания формы, которая будет вызывать скрипт. Вот она:

Здесь все понятно? Эту форму ты сможешь помещать в любую страницу своего сайта. Только в случае, если она лежит не в одном каталоге с файлом stat.php, в параметре action измени адрес так, чтобы он соответствовал реальному размещению файла.

(Продолжение следует)

Рекомендуем ещё прочитать:






Данную страницу никто не комментировал. Вы можете стать первым.

Ваше имя:
Ваша почта:

RSS
Комментарий:
Введите символы или вычислите пример: *
captcha
Обновить





Хостинг на серверах в Украине, США и Германии. © sector.biz.ua 2006-2015 design by Vadim Popov