« Поставить закладку » « Сделать стартовой »

« Форумы » « Блоги » « Статьи » « Новости » « Файлы » « Realcoding IRC » « Site map » « Поиск »


Главная Главная
Анонсы Анонсы
Форумы Форумы
Каталог Каталог
Поиск Поиск
Опросы Опросы
Книжный магазин Книжный магазин
Реклама на сайте
Публикации Публикации
Партнеры Партнеры
Карта Карта сайта
Рассылки Рассылки
RSS экспорт
Настройки Настройки
О нас пишут О нас пишут
Контакты Контакты
Гостевая книга Гостевая книга



ПнВтСрЧтПтСбВс
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
    Популярное
Привязка данных к элементам управления и проверка корректности ввода данных в wxWidgets

Программно создаем Alias

Вектора

Что видят поисковые системы при заходе на сайт?

Индусские програмисты

Разработка CGI приложений на Дельфи

Функция AccessResource

Функция date() - вывод даты и времени в PHP

Рисуем график функции

Функция CountVoiceNotes




    Архив файлов



    Сообщества

    Документация

    Кто на сайте
Вы не зарегистрированы.
Имя:

Пароль:

Запомнить

Регистрация позволит Вам пользоваться дополнительными сервисами.
Сейчас на сайте:
Гостей: 147
Пользователей: 0

Статьи:: Интернет технологии :: PHP :: Глава 10. PHP: Система оценки материалов



отправить ссылку другу версия для печати  Обсудить на форуме

Глава 10. PHP: Система оценки материалов

* РНР: система оценки материалов

В этой главе будет разобран сценарий, позволяющий посетителям выставлять оценки размещенным на сайте материалам. Ранее не использованных команд в нем почти нет, так что просто следите за логикой программы.
Сначала подумаем. Что должен делать код выставления оценки? Ну вначале, наверное, принимать от посетителя значение оценки (скажем, из формы с элементами <select. . .>. . .<option>. . ..). Однако, если эта оценка является первой за всю историю существования статьи, то необходимо записать ее в файл. Если же ранее статья уже была оценена, то следует считать имеющееся значение из файла и вычислить среднее арифметическое всех оценок, включая только что добавленную. В самом деле, нам ведь нужна именно средняя оценка, не так ли? А затем это новое значение средней оценки необходимо в тот же файл и записать.
Среднюю оценку можно посчитать по очевидной формуле



(средний балл*количество оценок)+новодобавленная оценка /
количество оценок + 1

Кроме того, среднюю оценку желательно показать и посетителю. Простая вставка файла с оценкой в страницу со статьей с помощью команды include не является изящным решением, так как значение средней оценки может быть выражено и довольно длинной десятичной дробью. Следовательно, оценку желательно округлить хотя бы до сотых, а лучше - до десятых.
Далее. Что должно произойти, когда посетитель выставит статье оценку? Первое, что приходит в голову - это отправить его назад на статью, которую он оценивал. Ведь направляли же мы в сценарии в прошлой главе посетителя назад в гостевую книгу после отправки им в.нее сообщения? Однако посетитель уже ведь прочитал статью, - зачем ему ее выводить снова, тратя его время в Сети, а, значит, и деньги. Куда как лучше после выставления оценки отправлять посетителя на специальную страницу с благодарностью о выполненном им действии и каталогом статей или разделов сайта.
Желательна также и реализация "защиты от накруток", т. е. нельзя давать одному и тому же посетителю возможность голосовать несколько раз. Для этого можно использовать cookie, т. е. помечать с помощью cookie браузер посетителя при выставлении им оценки и впоследствии позволять выставлять оценку только при отсутствии такого cookie.

Комментарий:
Cookie - это файл в специальном формате, который присылается сервером браузеру посетителя сайта, расположенном на этом сервере. Браузер, если он поддерживает cookie (и эта поддержка в нем не отключена), помещает его в особое место и впоследствии отправляет назад на сервер при поступлении от него запроса. Иными словами, cookie позволяет серверу хранить свою информацию на компьютерах посетителей и считывать ее оттуда при необходимости. Подробнее о cookie читайте в гл. 8.

Бесспорно, использование cookie - не очень надежная подобная защита. Ничего не мешает посетителю удалять cookie перед каждой новой попыткой выставления оценки или использовать разные браузеры, да и на общедоступных компьютерах проголосовать можно будет лишь единожды независимо от числа их пользователей до тех пор, пока cookie не будет удален. Но хоть что-то...
Наверняка на сайте будет находиться немало статей, к которым стоит добавить форму выставления оценок. Для того чтобы не вставлять в каждый файл множество строк одинакового кода, стоит выполнить весь код выставления оценки в отдельном модуле и включать его с помощью команды include в статьи, оценка которых посетителями необходима.
Итак, код выставления оценок разместится в двух файлах, один из которых предназначен для вставки в страницы со статьями, а второй содержит в себе текст благодарности посетителю за оценку. Допустим, первый файл будет называться niz.php, а второй - otziv.php. Что ж, приступим к самому тексту кода.
В каждый файл со статьей, в то место, где должна располагаться форма для выбора оценки, следует вставить одну строчку кода:

<?php include ("niz.php"); ?>

* Файл niz.php

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

<?php

Файлы со значениями среднего балла и количества оценок будут храниться в папке с именем cnt. Запишем для удобства ее имя в переменную:

$dirct="cnt";

А сами эти файлы будут иметь имена, составляемые на основе имени файла со статьей. Сначала "вытащим" это имя из полного имени файла (пояснения к используемым функциям смотрите в предыдущей главе):

$nom=substr(basename($PHP_SELF), 0, -4);

...а сами файлы назовем на основе этого имени, получив имя файла с количеством оценок прибавлением к нему окончания "kol", а имя файла со средним баллом - окончания "est" (рис. 10.1):

$kolvooc="$nom"."kol"; $ocenka="$nom"."est";

Рис. 10.1. Файлы системы оценивания.
Слева - статьи, файлы со сценариями и папка с файлами оценок, справа -содержимое этой папки


Теперь выведем сведения об уже выставленных оценках.

echo ("Оценок этой статье - ");

Если файл со сведениями о количестве оценок существует (он создается при первом оценивании)...

if (file_exists("$dirct/$kolvooc")==True)
{

...то вставим его значение в документ.

include ("$dirct/$kolvooc");

Если же такового файла нет, т. е. документ ни разу не оценивался...

}
else
{

...выведем значение "0".

echo ( " 0 " ) ;
}

Если файл со средним баллом существует...

if (file_exists("$dirct/$ocenka")==True)
{

...то надо вывести его значение.

echo (". Средний балл - ");

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

$hdl в fopen("$dirct/$ocenka", "r+");

...и считаем в переменную Ssred все содержимое этого файла.

$sred = fread($hdl, filesize("$dirct/$ocenka"));

Примечание:
Функция fread (дескриптор файла, длина считываемого фрагмента) считывает из открытого файла, для которого получен указанный в ее первом параметре дескриптор, столько байт, сколько указано в ее втором параметре (чтение начинается с местонахождения так называемого указателя файла — отметки, показывающей текущее место работы с файлом; указатель двигается при чтении или записи в файл, а также при использовании команды fseek).
Функция filesize (полный путь к файлу) возвращает размер указанного в ее параметре файла в байтах.

Файл можно закрыть...

fclose($hdl);

...а переменную $sred - округлить до десятых

$sred=round ($sred, 1);

Примечание:
Функция round (число, количество разрядов) округляет дробное число в ее первом параметре до количества разрядов, указанного в ее втором параметре. Скажем, round (число, 1) округлит число до десятых, round (число, 2) - до сотых и т. д.

В РНР до четвертой версии функция round могла округлять числа только до целых, поэтому в том случае, если вы располагаете только такой версией РНР, то команда округления до десятых должна выглядеть как

$sred=(round ($sred*10))/10; ...и вывести на страницу.
echo ("$sred.");
}

Имя cookie, в котором будет находиться информация о том, голосовал ли посетитель за данную статью или нет, тоже будет образовываться из имени файла статьи. Запишем это имя в переменную $haveestim...

$haveestim=$nom."haveest";

...и проверим, определена ли переменная с таким именем - т. е. установлен ли одноименный cookie или нет (рис. 10.2). Можно было бы также проверять, какое значение имеет данная переменная, но для нашего сценария это неважно - если переменная установлена и cookie определен, то посетитель уже голосовал за данную статью: ведь cookie с данным именем устанавливается ему в этом и только в этом случае.

if ($$haveestim=="")

Обратите внимание на имя проверяемой переменной - это имя само является значением переменной Shaveestim (подобную конструкцию допускают правила РНР, подробнее смотрите в гл. 3).

Рис. 10.2. Содержимое cookie - пометки о состоявшемся голосовании

Поскольку значения cookies доступны и через массив $HTTP_COOKIE_VARS[], то проверить наличие cookie можно и на основе анализа значений этого массива:

if ($HTTP_COOKIE_VARS[$haveestim]=="")

или в РНР версии 4.1 и выше

if ($_COOKIE[$haveestim]==" ")

Комментарий:
Помните, что доступность данных cookie зависит от настроек в файле php.ini (рис.10.3) - если в файле php.ini установлен в on параметр register_globals, то содержимое cookie доступно в сценарии в переменной с тем же именем, что и cookie, а если ephp.ini установлен в on параметр trackjvars, то содержимое cookie доступно в сценарии в одноименном с этим cookie элементе массива SHTTPCOOKIEVARSfJ (с РНР 4.1 -и $_СООК1Е[]).

Использовать массивы $HTTP_COOKIE_VARS[] и $_СООК1Е[] лучше с точки зрения безопасности. Если в сценарии используются одноименные cookie переменные, а не элементы этих массивов, то в том случае, если cookie не установлен, злоумышленник все равно может передать сценарию значение такой переменной, попросту указав его в адресной строке браузера. В указанные же массивы попадают исключительно полученные с cookie данные. Однако в рассматриваемом в данной главе сценарии это несущественно. 118

Рис. 10.3. Файл php.ini. Вышеупомянутые настройки

Если cookie не установлен - т. е. посетитель ранее не голосовал за данную статью...

{

то выведем ему форму для голосования

. ?>
<form method="post" action="otziv.php">

Передадим в скрытом поле формы имя файла со статьей без расширения - для определения на основе него сценарием-обработчиком имен файлов со сведениями о количестве оценок и среднем балле, а также полное имя, вместе с путем, файла со статьей - для вывода ссылки "Назад" на странице со сценарием-обработчиком. В принципе можно было бы передавать через форму только полное имя файла со статьей, а "чистое" имя файла статьи определять в сценарии-обработчике точно так же, как и в сценарии из niz.php - на основе функции basename, но для сокращения длины кода в обработчике воспользуемся передачей его через форму.

<input name="nom" type="hidden" value="<?php echo $nom; ?>">
<input type=hidden name=nazad value=<?php echo ($PHP_SELF); ?>>

Выведем форму ввода оценки:
Поставьте оценку статье:

<SELECT NAME=ocen>
<OPTION VALUE=5>5 (Отлично)
«DPTION VALUE=4>4 (Хорошо)
<OPTION VALUE=3>3 (Удовлетворительно)
<OPTION VALUE=2>2 (Плохо)
<OPTION VALOE=1>1 (Очень плохо)
</SELECT>

В результате в сценарий-обработчик будет передана переменная Socen (и одноименные элементы массивов $HTTP_POST_VARS, $_POST при соответствующих версиях РНР и настройках в php.ini) со значением, равным параметру value выбранного пользователем пункта выпадающего списка.
Выведем кнопку отправки формы (рис. 10.4).

Рис. 10.4. Система оценивания в действии...

<input name="submit" type="submit" value="Послать оценку"></form>
<?php

А если посетитель уже голосовал за данную статью - т. е. cookie с соответствующим именем у него установлен...

}
else {

...то сообщим ему об этом (рис. 10.5).

echo ("Вы уже голосовали за эту статью!");

Рис. 10.5. ...но голосование уже состоялось

Вот и все.

* Файл otziv.php

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

<?php

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

$namecook=$nom."haveest";

...и весь дальнейший код выполним только в том случае, если такого cookie установлено не было.

if ($$namecook=="")

Примечание:
Вместо этой строки можно использовать строку
i f ($HTTP_COOKIE_VARS[$haveestim]=="") или в PHP версии 4.1 и выше — строку
if ($_COOKIE[$haveestim]=="") как уже указывалось выше.

Комментарий:
Казалось бы — а зачем, собственно, проверять на этой странице, установлен ли cookie? Ведь форма для выставления оценки на предыдущей странице может появиться на ней только в том случае, если cookie отсутствует, не так ли? Но все дело в том, что посетитель, желающий сделать "накрутку" статьи, проголосовав за нее множество раз, вполне может сохранить на своем компьютере локальную копию статьи с формой для выставления оценки, и уже с нее осуществлять голосование. Ясно, что отображение формы на локальной копии страницы от наличия или отсутствия cookie не зависит, — поэтому и приходится осуществлять проверку еще и здесь.

Итак, если посетитель еще не голосовал за данную статью...

{

...установим cookie, говорящий, что такое голосование наконец совершилось. Время жизни cookie установим в месяц - пожалуй, хватит. (Пояснение по функции установки cookie смотрите в гл. 8).

SetCookie("$namecook","1",time()+2 592000);

Запишем в переменные имена директории с файлами оценок и самих этих файлов:

$dirct="cnt";
$kolvooc="$nom"."kol";
$ocenka="$nom"."est";

Если файлы оценок не существуют (т. е. выставляемая оценка - вообще первая по счету)...

if ((file_exists("$dirct/$kolvooc")!=True)||
(file_exists("$dirct/$name2")!=True)) {

...то запишем в файл со сведениями о количестве оценивших число 1 (так ведь и есть, не правда ли?)...

$hdll = fopen("$dirct/$kolvooc", "a+"); fwrite($hdll,l); fclose($hdll);

...а в файл со сведениями о среднем балле - выставленную посетителем оценку (она ведь и есть "среднее" от самой себя):

$hdl2 = fopen("$dirct/$ocenka", "a+");
fwrite($hdl2,$ocen);
fclose($hdl2);

Если же файлы со сведениями об оценке уже существуют...

else

...то считаем для начала содержимое файла с количеством оценок в переменную

kvo...
$hdll = fopen("$dirct/$kolvooc", "r+");
$kvo ¦ fread($hdll, filesize("cnt/$kolvooc"));

...а затем увеличим значение этой переменной на 1 - что и будет новым количеством оценок, с учетом последней выставленной:

$kvo++;

Теперь нам надо вернуть точку считывания (так называемый "указатель") в начало файла - для того, чтобы записать в файл новое значение количества оценок. Ведь в результате проведения операции чтения количества оценок из файла точка считывания - указатель - переместилась в его конец. Для совершения данной операции воспользуемся командой rewind:

rewind($hdll);

Примечание:
Команда rewind (дескриптор открытого файла) перемещает точку считывания и записи данных в файл (т. е. указатель файла), в начало этого файла. Если вы записываете что-либо в файл после считывания из него данных, то вам необходимо перед записью воспользоваться этой командой.
Следует помнить, что если файл был открыт командой fopen с параметром а или a+, то независимо от положения указателя запись новых данных командой fwrite будет осуществляться вконец файла.

Запишем новое значение количества оценок в предназначенный для хранения этой величины файл...

fwrite($hdll,$kvo);

...и закроем его.

fclose($hdll);

Теперь разберемся со средним баллом. Откроем файл, где хранится его значение...

$hdl2 = fopen("$dirct/$ocenka", "r+");

...запишем это значение в переменную...

$sred= fread($hdl2, filesize("cnt/$ocenka"));

...и рассчитаем новую величину среднего балла - на основе его старого значения, а также информации о количестве оценок и новой оценки.

$sred=($sred*($kvo-l)+$ocen)/$kvo;

Теперь запишем эти сведения в предназначенный для них файл -точно так же, как и парой абзацев выше.

rewind($hdl2); fwrite($hdl2,$sred); fclose($hdl2);

Собственно, и все.
Можно выводить информацию посетителю об итоговом результате (рис. 10.6) или краткую благодарность.

echo ("Благодарим вас за оценку!");

Рис. 10.6. После успешного голосования

Рис.10.7. После попытки повторного голосования

Если же посетитель уже голосовал за данную статью...

}
else {

...то сообщим ему об этом (рис. 10.7) - и ничего делать не станем, echo ("Вы уже голосовали за эту статью!");

}
Сценарий закончен. ?>

Остальной текст страницы - на ваше усмотрение. Разместите на ней каталог разделов сайта, список статей или просто красиво оформите. Если же пожелаете поставить на ней ссылку на оцениваемую статью - то просто разместите в нужном месте выводящий эту ссылку код:

<?php echo ("<a href=$nazad>Ha3afl</a>"); ?>

Переменная Snazad была передана через форму, помните?

Комментарий:
В данном сценарии для упрощения восприятия значения переменных, передаваемых через форму, брались из одноименных переменных в сценарии-обработчике - так как на безопасность работы программы это здесь не влияет: даже если злоумышленник подставит значение переменной cookie в адресную строку, то он только потеряет возможность проголосовать, и ничего больше. Если вы желаете сделать код лучше соответствующим правилам РНР - замените их на одноименные элементы массива $HTTP_POST_VARS[] (в РНР версии до 4.1) или SPOSTfJ (в РНР версии 4.1 и старше).

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

* Текст сценария

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

Вставка в файлы со статьями:

<?php include ("niz.php"); ?>

Файл niz.php

<?php
$dirct="cnt";
$nom=substr(basename($PHP_SELF), 0, -4); $kolvooc="$nom"."kol"; $ocenka="$nom"."est"; echo ("Оценок этой статье - "); if (file_exists("$dirct/$kolvooc")==True) {
include ("$dirct/$kolvooc"); }
else {
echo (" 0") ; }
if (file_exists("$dirct/$ocenka")==True) {
echo (". Средний балл - "); $hdl = fopen("$dirct/$ocenka", "r+"); $sred = fread($hdl, filesize("$dirct/$ocenka")); fclose($hdl); $sred=round ($sred, 1); echo ("$sred."); }
$haveestim=$nom."haveest"; if ($$haveestim=="")
<form method="post" action="otziv.php">
<input name="nom" type="hidden" value="<?php echo $nom; ?>">
<input type=hidden name=nazad value=<?php echo ($PHP_SELF); ?>>
Поставьте оценку статье:
<SELECT NAME=ocen>
<OPTION VALUE=5>5 (Отлично)
<OPTION VALUE=4>4 (Хорошо)
<OPTION VALUE=3>3 (Удовлетворительно)
<OPTION VALUE=2>2 (Плохо)
<OPTION VALUE=1>1 (Очень плохо)
</SELECT>
<input name="submit" type="submit" value="Пocлaть оценку"></form>
<?php
}
else {
echo ("Вы уже голосовали за*эту статью!"); } ?>

Файл otziv.php

<?php
$namecook=$nom."haveest"; if ($$namecook=="") {
SetCookie("$namecook","1",time()+2592000);
$dirct="cnt";
$kolvooc="$nom"."kol";
$ocenka="$nom"."est";
if ((file_exists("$dirct/$kolvooc")!=True) ||(file_exists("$dirct/$name2")!=True))
{
$hdll = fopen("$dirct/$kolvooc", "a+");
fwrite($hdll,1)j
128
fclose($hdll);
$hdl2 = fopen("$dirct/$ocenka", "a+");
fwrite($hdl2,$ocen);
fclose($hdl2);
else
$hdll = fopen("$dirct/$kolvooc", "r+");
$kvo = fread($hdll, filesize("cnt/$kolvooc"))
$kvo++;
rewind($hdll);
fwrite($hdll,$kvo); .
fclose($hdll);
$hdl2 = fopen("$dirct/$ocenka", "r+");
$sred= fread($hdl2, filesize("cnt/$ocenka"));
$sred=($sred*($kvo-l)+$ocen)/$kvo;
rewind($hdl2);
fwrite($hdl2,$sred);
fclose($hdl2);
echo ("Благодарим вас за оценку!"); else echo ("Вы уже голосовали за эту статью!");

Ниже в этом же файле:

<?php echo ("<a href=$nazad>Haзад</a>"); ?>

 




Рубрика: PHP

{BLOCK|article|lastarticle||non.tpl}

Цитата дня (все,добавить):

Портал фрилансеров

работа на дому


    Рубрикатор

Программирование

C/С++
Обучение
Windows API
XAML
Моделирование
Паттерны
Visual Basic 7 .NET
WxWidgets
Функции WinApi
Функции С++
Разработка под Mac OS
Eiffel
Visual Studio 2008
UI дизайн
Алгоритмы
Конкурсные статьи
Turbo Pascal
Visual Studio
CASE-средства
Visual Studio 2005
Без VCL
Delphi
Тех. документация
Тестирование
Software Testing
ООП
TCP/IP
Google Android
Windows Installer
.NET Framework
Драйвера
C# C Sharp
Справка
Проектирование
Информ. системы
Visual Basic
Assembler
Оптимизация кода
Gtk+
Компоненты
Реинжиниринг
Управление проектами
Extreeme programming
Lotus Notes
Алгебраическое проектирование


Интернет технологии

PHP
Perl
ASP
WAP
Cookies
SSI
CGI
Web Servers
VB Script
DNS
CSS
XML
Html
Java Script
Java2ME
Firewall
Flash
.htaccess
Apache
VRML
Протоколы
Поисковые системы
Технология JAVA
Учебник по PHP
Учебник по JavaScript
Учебник по XML
Java Q&A
AJAX
DHTML
XHTML
Dreamweaver
Web 2.0
Python
Вебмастеру
Cisco
Ruby on Rails
Silverlight

Базы данных

Access
InterBase
MySQL
Oracle
ADO .NET
Основы SQL
Учебник по Access 2002
MS
Microsoft FoxPro
Доступ к данным
XML в MS SQL Server 2000
ODBC и MyODBC
Обучение
Caché
DB2
PostgresSQL
Sybase
Теория
Хранилища данных
Безопасность
Реляционные данные
MySQL и mSQL

Остальное:

Разное
Обзоры книг
Безопасность
Графика и дизайн
Юмор
Linux
Фракталы
Microsoft Axapta
Многоядерность
Сети
Microsoft Office
Работа
MS-DOS
Криптография
Графика и игроделание
Новости SDK
Системы защиты
Учебник по AutoCad
CVS
Windows XP
Windows Server 2003
Windows Vista
Windows 7
Мероприятия