|
Последняя модификация: 10.08.2014 г Страница загружена с адреса: http://webdesign.site3k.ru/conjuncture/append/d/golos.html Создание на сайте голосованияУстроить на сайте голосование с помощью PHP-скрипта проще простого. Приведу пример, совсем не простого голосования в котором запрашиваются не просто мнение по какому-то вопросу, а мнение сразу по ряду вопросов. Используя данный пример, легко, как усложнить, так и упростить голосование, на ваше усмотрение. Содержимое файла form.php<html><!-- Обычное начало страницы --> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <META name="keywords" content=""> <META name="description" content=""> <META name="Author" content="Красносельский К. К."> </head> <BODY TEXT=Black> <h1>Голосование</h1> <center> <form name="frm" action=<?php echo $_SERVER["SCRIPT_NAME"];?>><!-- Начинается форма. Адрес action пусть даст сам сервер. Используется метод GET, файл может иметь любое расширение --> <table cellspacing=0 cellpadding=0 border=0> <tr><td colspan=2 align=center><B>Что вас интересовало:</B></td></tr> <tr><td><input type=radio name="them" value=1>Компьютер (<?php echo $total[1][1];?>): <!-- из массива будет получено количество голосов --></td> <td><img src="img.php?<?php echo round($total[1][1]/$golosov[1]*100,2);?>"> <!-- На основании этой формулы будет получен рисунок для графического отображения результатов --></td></tr> <tr><td><input type=radio name="them" value=2>Программы (<?php echo $total[1][2];?>):</td><td><img src="img.php?<?php echo round($total[1][2]/$golosov[1]*100,2);?>"></td></tr> <tr><td><input type=radio name="them" value=3>Веб-дизайн (<?php echo $total[1][3];?>):</td><td><img src="img.php?<?php echo round($total[1][3]/$golosov[1]*100,2);?>"></td></tr> <tr><td><input type=radio name="them" value=4>Гуманитарные науки (<?php echo $total[1][4];?>):</td><td><img src="img.php?<?php echo round($total[1][4]/$golosov[1]*100,2);?>"></td></tr> <tr><td><input type=radio name="them" value=5 CHECKED>Другое (<?php echo $total[1][5];?>):</td><td><img src="img.php?<?php echo round($total[1][5]/$golosov[1]*100,2);?>"></td></tr> <tr><td colspan=2 align=center><B>По указанной теме вы хотели найти:</B></td></tr> <tr><td><input type=radio name="tipe" value=1>Документацию (<?php echo $total[2][1];?>):</td><td><img src="img.php?<?php echo round($total[2][1]/$golosov[2]*100,2);?>"></td></tr> <tr><td><input type=radio name="tipe" value=2>Справочники (<?php echo $total[2][2];?>):</td><td><img src="img.php?<?php echo round($total[2][2]/$golosov[2]*100,2);?>"></td></tr> <tr><td><input type=radio name="tipe" value=3>Статьи (<?php echo $total[2][3];?>):</td><td><img src="img.php?<?php echo round($total[2][3]/$golosov[2]*100,2);?>"></td></tr> <tr><td><input type=radio name="tipe" value=4 CHECKED>Другое (<?php echo $total[2][4];?>):</td><td><img src="img.php?<?php echo round($total[2][4]/$golosov[2]*100,2);?>"></td></tr> <tr><td colspan=2 align=center><B>Насколоько вы остались довольны:</B></td></tr> <!-- Этот вопрос не имеет предустановленного значения (значения по умолчанию) и будет использоватся для контроля: голослвал ли посетитель, или просто нажал на кнопку, не задумываясь --> <tr><td><input type=radio name="result" value=1>Очень (<?php echo $total[3][1];?>):</td><td><img src="img.php?<?php echo round($total[3][1]/$golosov[3]*100,2);?>"></td></tr> <tr><td><input type=radio name="result" value=2>Вполне (<?php echo $total[3][2];?>):</td><td><img src="img.php?<?php echo round($total[3][2]/$golosov[3]*100,2);?>"></td></tr> <tr><td><input type=radio name="result" value=3>Почти (<?php echo $total[3][3];?>):</td><td><img src="img.php?<?php echo round($total[3][3]/$golosov[3]*100,2);?>"></td></tr> <tr><td><input type=radio name="result" value=4>Не очень (<?php echo $total[3][4];?>):</td><td><img src="img.php?<?php echo round($total[3][4]/$golosov[3]*100,2);?>"></td></tr> <tr><td><input type=radio name="result" value=5>Не доволен (<?php echo $total[3][5];?>):</td><td><img src="img.php?<?php echo round($total[3][5]/$golosov[3]*100,2);?>"></td></tr> <tr><td colspan=2 align=center><B>Как вы попали на сайт:</B></td></tr> <tr><td><input type=radio name="link" value=1>Перешел с поисковика (<?php echo $total[4][1];?>):</td><td><img src="img.php?<?php echo round($total[4][1]/$golosov[4]*100,2);?>"></td></tr> <tr><td><input type=radio name="link" value=2>Перешел с каталога сайтов (<?php echo $total[4][2];?>):</td><td><img src="img.php?<?php echo round($total[4][2]/$golosov[4]*100,2);?>"></td></tr> <tr><td><input type=radio name="link" value=3>Перешел по баннеру (<?php echo $total[4][3];?>):</td><td><img src="img.php?<?php echo round($total[4][3]/$golosov[4]*100,2);?>"></td></tr> <tr><td><input type=radio name="link" value=4>По ссылке с другого сайта (<?php echo $total[4][4];?>):</td><td><img src="img.php?<?php echo round($total[4][4]/$golosov[4]*100,2);?>"></td></tr> <tr><td><input type=radio name="link" value=5>Рекомендовали друзья (<?php echo $total[4][5];?>):</td><td><img src="img.php?<?php echo round($total[4][5]/$golosov[4]*100,2);?>"></td></tr> <tr><td><input type=radio name="link" value=6>Давний посетитель (<?php echo $total[4][6];?>):</td><td><img src="img.php?<?php echo round($total[4][6]/$golosov[4]*100,2);?>"></td></tr> <tr><td><input type=radio name="link" value=7 CHECKED>Другое (<?php echo $total[4][7];?>):</td><td><img src="img.php?<?php echo round($total[4][7]/$golosov[4]*100,2);?>"></td></tr> <tr><td colspan=2 align=center><B>Всего проголосовало: </B><?php echo $golosov[1].$WriteText;?></td></tr> </table> <input type=submit name=golos value="Голосовать"> </form> </center> </body> </html>
Приведенный код только внешний вид страницы. Теперь необходимо снадбить его скриптами. Начальные установки скрипта<?php // Первый запуск скрипта, инициализация переменных $total = array( // Создадим двухмерный массив для данных ключи которого, для удобства, начинаются с единицы 1 => array(1 => 0,0,0,0,0), //"them" элементы начинаются с индекса 1 2 => array(1 => 0,0,0,0), //"tipe" хранятся знечения tipe (и т. д.) 3 => array(1 => 0,0,0,0,0), //"result" 4 => array(1 => 0,0,0,0,0,0,0) //"link" ); $file_name=".data.txt"; // Имя файла начинается с точки, поэтому он недоступен для постороних В начале скрипта создается массив из которого будут браться значения для отображения в форме (элементы вроде <?php echo $total[1][1];?>). Создание массива необходимо, чтобы при первом запуске скрипта или ошибке доступа к файлу, хранящему статистику, на страницу не выдавалось сообщение о неопределенной переменной. В дальнейшем, массив будет браться из файла и переопределять пустые значения, заданные здесь. Применение многомерного массива в данной ситуации является наиболее эфективным и компактным решением. Для языков, не поддержывающих многомерные массивы потребовались бы очереди в памяти или непосредственная запись в базу данных. В худшем случае, пришлось бы использовать множество переменных. Но каждый из этих вариантов все более и более громоздки и медлительны (можете попробовать идти иным путем). Переменная «$file_name» определяется здесь, чтобы не определять ее дважды там, где она будет использоваться. Проверка пользовательского ввода и сохранение рузультатовif (@$golos){ if (@$them and @$tipe and @$result and @$link) {// проверка наличия всех полей // Следующая строка - проверка типа данных, которые могут быть неправильными, если отправлены в обход формы (JavaScript будет бессилен) if (is_numeric($them) and is_numeric($tipe) and is_numeric($result) and is_numeric($link)) { // Дальше - проверка диапазона (JavaScript будет бессилен) if (ereg("([1-5]{1})",$them) and ereg("([1-4]{1})",$tipe) and ereg("([1-5]{1})",$result) and ereg("([1-7]{1})",$link)) { // ЗАПИСЬ ДАННЫХ----------------------------------------- $readable=is_readable($file_name);// определить доступен ли файл на чтение @$file=fopen($file_name,"a+"); // открыть файл (создав, если его нет) if (@$file) {// если успешно открыт flock($file,LOCK_EX); // ждем , пока не заблокируем файл if ($readable){ // если файл существовал до момента открытия/создания $total=unserialize(fread($file, filesize($file_name))); }// если файл пустой (свежесозданный) унсериализировать нельзя - будет ошибка $total[1][$them] +=1; $total[2][$tipe] +=1; $total[3][$result] +=1; $total[4][$link] +=1; // Здесь мы учитываем номер ответа, который пришел к нам из формы, // увеличив соответствующее значение в массиве ftruncate($file,0); // очищаем все содержимое файла, независимо от того, был он или не был fwrite($file, serialize($total)); // Запись обновленных данных в файл fflush($file); // сбрасываем все изменения на диск flock($file,LOCK_UN); // разблокируем файл fclose($file); Header("Location: http://".$_SERVER["SERVER_NAME"]. $_SERVER["SCRIPT_NAME"]. "?return=1"); // мнение учтено, перегружаем страницу exit(); }else{ $return=2; // Ошибка открытия файла, можно отправить отчет администратору } // ----------------------------------------- }else{ $return=3; // неправильный диапазон } }else{ $return=4; // Неправильный тип } }else{ $return=5; // не все опции } } Проверка типа данных в данном случае не имеет большого значения. Главное проверить попадание в диапазон (попробуйте на своей копии убрать проверку диапазона и в одну из переменных занести число вне его). Если значения не подходят по типу, то и в диапазон они не попадут, но, отдельная проверка на тип, позволяет сделать более точное сообщение об ошибке. Дальше, мы открываем файл, блокируем, считываем, одним оператором, благодаря функции unserialize, восстанавливая сохраненный в файле массив. Далее, используем тот факт, что переменные $them и ей подобные, поступая из формы (и предварительно проверянные), содержат номера выбранных при голосовании элементов. Таким образом, конструкция типа $total[1][$them] +=1, увеличивает значение именно той ячейки первого подмассива, на которую указывает значение переменной $them. Например:
Аналогично с другими подмассивами. Без использования массивов задача значительно усложнилась бы. Далее, мы очищаем файл, с помощью функции serialize преобразовываем массив в формат, пригодный для хранения в текстовом файле, даем команду записи, сбрасываем буферы, разблокируем и закрываем файл. Закончив запись, заставляем браузер заново считать скрипт, добавив к адресу параметр return=1, который будет означать что, данные успешно всесены. В случае каких-либо неудачь, переадресации браузера не потребуется. Достаточно в переменных, одноименых параметру, передаваемому в адресе в случае удачи (return), дать определенные значения, а позже проанализировать их. Чтение данных из базыЭта часть скрипта должна запускаться, если файл данных еще не открывался, чтоб не читать его дважды. Такое, обычно происходит при простом открытии страницы с формой. if (!@$file){ // Если файл еще не открывался // ЧТЕНИЕ ДАННЫХ---------------------------------------- @$file=fopen($file_name,"r"); // открыть файл if (@$file) {// если успешно открыт $total=unserialize(fread($file, filesize($file_name))); } @fclose($file); // закрыть // @ в $total и других, стоит для первого запуска, когда файла еще нет // ---------------------------------------- } Практически, эта часть упрощенно повторяет ту, которая отвечала за чтение и запись. Предварительная обрабатка данных для отображения в браузере// ОБРАБОТКА ПРОЧИТАННЫХ ДАННЫХ---------------------------------------- for($i=1;$i <= count($total); $i++) { $golosov["$i"]=array_sum($total["$i"]); // подсчитаем общее количество голосов по каждой строке if ($golosov["$i"] == 0) {$golosov["$i"]=1;} // Для избежания ошибки деления на ноль когда еще никто не голосовал // (правда счетчик покажет, что голосовал 1 человек, но это не важно - сгрузив скрипт на сайт, мы проголосуем разок, для теста, и дальше все будет правильно) } if (@$golosov[1]);// @ стоит для первого запуска { if (substr($golosov[1],strlen($golosov[1])-2,1)==1) // 10 -19, 110 - 119, и т. д. { $WriteText=' человек.'; } elseif (substr($golosov[1],strlen($golosov[1])-1,1) > 1 && substr($golosov[1],strlen($golosov[1])-1,1) < 5) // заканчивается на 2 или 3, или 4 { $WriteText=' человека.'; } else { $WriteText=' человек.'; // все остальные } } // ---------------------------------------- ?> На этом основные скрипты завершаются. Теперь мы знаем сколько человек всего проголосовало (это значение содержится в каждом элементе массива $golosov, что, при желании, можно использовать для проверки: значения должны быть одинаковыми). И имеем нормальные окончания для вывода статистики. Все эти фрагменты скрипта необходимо поместить перед началом страницы (до тега <HTML>). Но это еще не все: перед началом формы, следует поместить код: <?php switch (@$return) { case 1: echo "<h2><font color=#215582>Спасибо, Ваше мнение учтено!</font></h2>"; break; case 2: echo "<h2><font color=Maroon>Извините, нам не удалось произвести запись в базу. Попробуйте позже.</font></h2>"; break; case 3: echo "<h2><font color=red>В одной из переменных неправильный диапазон. Вы явно пытаетесь голосовать минуя форму!</font></h2>"; break; case 4: echo "<h2><font color=red>В одной из переменных неправильный тип данных. Вы явно пытаетесь голосовать минуя форму!</font></h2>"; break; case 5: echo "<h2><font color=red>Вы отметили не все опции!</font></h2>"; break; default: echo "<h2>Ваше мнение о сайте:</h2>"; } ?> Который, исходя из значений переменной return, будет выводить либо сообщение об успешности голосования, либо сообщение о проблеме, либо обычную строку «Ваше мнение о сайте». Но Самое интересное, только начинается. Страница нуждается в графическом отображении резальтатов голосования. Это позволит сделать следующий скрипт (его имя должно соответствовать указанному в атрибутах src, используемых на странице расунков img.php). Файл img.phpЭто довольно просотй файл
Если не вашем сервере не поддерживается Gif-формат, замените в нем все «Gif» на «PNG» или «JPG». Не смотря на свою простоту, файл оказывается очень полезным и может применятся не только в процедуре голосования. Параметры, которые ему передаются (вроде round($total[3][5]/$golosov[3]*100,2)) определяют процент людей, давших определенный ответ по теме и, используются скриптом, для задания размеров и вывода текста. Сохраните файлы img.php и form.php, и наслаждайтесь собственным голосованием. После отладки серверного скрипта, полезно добавить контроль данных на стороне клиента, для чего добавить в заголовочную часть страницы такой скрипт: <SCRIPT LANGUAGE="JavaScript"><!-- function test(){ for (i=0, testvar=false; i < document.frm.result.length; i++){ if (document.frm.result[i].checked){ testvar=true; break; } } if (testvar==false){alert('Вы отметили не все опции!'); return false;} } //--></SCRIPT> И реакцию на событие onsubmit в форму: <form name="frm" action=<?php echo $_SERVER["SCRIPT_NAME"];?> onsubmit="return test()"> Чтобы еще до отправки формы на сервер, проверить, все ли переключатели установлены. Пробежавшись по всем радиокнопкам с именем «result», данный скрипт проверит, есть ли среди них отмеченная и, если нет, не позволит отправить форму. Это уменьшит не только утомляемость посетителя, но и нагрузку на сервер и линию. Увидеть данный скрипт голосования на PHP в действии можно на странице статистики.
|