Вторник, 16.06.2026, 20:43
Приветствую Вас Гость | RSS
Поиск по каталогу
Главная страница | Каталог статей | Регистрация | Вход

Информационные технологии
Форма входа
Меню сайта

Категории каталога
php [246]
perl [1]
perl
ASP [1]
AJAX [0]

Друзья сайта

Наш опрос
Оцените мой сайт
Всего ответов: 69

Начало » Статьи » Web программирование » php

Системы голосований на РНР 1
Виват, дорогие читатели ! Сегодня, в этот ничем не знаменательный день, а может быть совершенно наоборот, я написал "это", а сейчас вам предстоит всё "это" прочитать, а самое главное понять. Сегодня мы с вами посвятим время такой теме, как "Системы голосований на РНР".

Да, на сегоднешний день этой довольно интересной теме посвященны целые горы статей, но как-то маловато статей рассказывают всё чётко и во всех мелочах. Именно про эти мелочи и чётко мы сейчас и поговорим. Наверное больше половины из вас участвовали в разных интерактивных голосования, форумных pool'ах, и в прочей дребедени. Но как это всё построено ? На каком алгоритме это всё "пашет" ?

А алгоритмов существует великое множество. Сейчас я перечислю самые популярные среди разработчиков:

XML- вопрос и ответы, храняться в одном XML файле, с которого через парсер и "достают" все данные для обеспечения работы голосований.

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

Хранение данных в БД (способ №1) - этот способ являеться самым рациональным, ведь он не требует особых ментальных усилий, при этом обеспечивая высокую продуктивнось, но для него, во-первых, требуеться наличие БД, во-вторых, этот метод занимает много физической памяти базы данных. Мы рассмотрим его в самом начале. Принцип таков: вопрос и прочие статические данных располагаються в некой абстрактной таблице "а", при этом ответы в таблице "б". На каждый ответ приходится ряд "р", таблице "а", который имеет ссылку на номер голосования находящегося в таблице "а". То есть между таблицей "а" и "б" устанавливаеться прямая связь. Почему я сказал, что этот способ требует немалого пространства в БД ? Так потому, что под каждый ответ выделяеться отдельный столбец, а это крайне не рационально в случае при работе с БД.

Хранение данных в БД (способ №2) - этот способ самый сложный среди всех вышеперечисленных, однако он не занимает много место, при этом он совмещает ответы, вопрос, и количество ответов в отной таблице, и в этой таблице ряд отводиться под всё голосование в целом, хотя эта компактность компенсируеться повышеной сложностью обновления данных, и засчёт каждого нового голоса. Принцип в том, что все ответы помещаються в одну строку, при чём в особом порядке, так, что позиции каждого ответа соответствует позиция значения количества голосов, людей которые проголосовали именно за этот вариант. Так же поле вариантов ответов, и соответственно количества голосов будут кодироваться в формате base64, для уменьшения размера конечной строки.

Всё, это были все варианты выполнения алгоритма процесса голосования, которые мы сегодня рассмотрим.

Лично мой выбор второй вариант хранения в БД, так как я автор данного способа, и он мне более по душе, но тем кто только начинает осваивать технологии Веб-программирования, я советую почитать про первый вариант при работе с БД. Что ж, теперь можно перейти к практической части, и она начнёться именно с первого варианта при работе с БД. Но я забыл сказать про довольно важную на мой взгляд деталь. Я забыл сказать про защиту от повторного голосования, это мы будем делать во всех голосования при помощи БД, поскольку именно этот способ обеспечивает полную целостность данных, ибо для доступа к БД третьим лицам им нужно будет иметь данные для доступа или взломать БД, что крайне проблематично, поэтому хакерам будет довольно сложно нанести скрипту урон в этой части. А файлы всегда можно удалить, даже если на них будет блокировка "666", то всё равно они защищены не в полном объёме.

Поэтому я выбрал БД. Посему сейчас вам нужно создать табличку для храния данных о пользователях которые уже проголосовали.

Структура таблички такова:


ТАБЛИЦА `alredy_vote`:
id- BIGINT- AUTO_INCREMENT- PRIMARY KEY
vote_id
- BIGINT- NOT NULL- UNIQUED
ip
- TEXT- NOT NULL


Название оставляю вам, но скажу что я буду использовать "alredy_voted". Что ж, а теперь на практику :)

Первый вариант при работе с БД.

Что ж, по моему мнению для тех кто называет себя программистами на "достаточном" уровне хватило бы одного только описания в начале, но во всяком случае я опишу данный способ со всеми частицами. Итак, с начала мы создадим две таблички в вашей базе данных, называйте их как хотите, но в статье я буду использовать названия "pools_answs" (для вариантов ответа) и "pools" (для самих голосований). Их структура сдедующая:


ТАБЛИЦА `pools`:
id- BIGINT- AUTO_INCREMENT- PRIMARY KEY
question
- TEXT- NOT NULL
status
- ENUM('on','off')- DEFAULT 'on'- NOT NULL

ТАБЛИЦА
`pools_answs`:
id- BIGINT- AUTO_INCREMENT- PRIMARY KEY
vote_id
- BIGINT- NOT NULL- UNIQUED
value
- TEXT- NOT NULL


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

Так же хочу упомянуть, что пользователь сам может устанавливать количество вариантов ответа. Конечно есть соблазн использовать DOM модель и любимый нами всеми JS (ведь так ?), но я воздержусь, и воспользуюсь простым и банальным параметром QUERY_STRING и старым, родимым $_GET интерфейсом. Что ж, давайте попытаемся воплотить всё это безобразие на "холсте" :)


<?
$count=isset($_GET['count'])? $_GET['count']:5;
if(!isset(
$_POST['add'])){
print
"<form action='' method='post' name='addPool'>";
print
"<table width='300' height='50' align='center'>";
print
"<tr><td colspan='2' style='text-align:center;'><input
size='40' type='text' name='question'
value='Введите вопрос голосования' onFocus='this.select();'></td>
</tr>"
;
print
"<tr><td style='text-align:center;' colspan='2'><button
onClick="
top.location='".$_SERVER['PHP_SELF']."?count=".($count+1)."'">
Добавить вариант</button></td></tr>"
;
for(
$i=0;$i<$count;$i++){
print
"<tr><td>Вариант ответа №".$i.":</td><td><input
type='text' name='answs[]'></td></tr>"
;
}
print
"<tr><Td colspan='2' style='text-align:center;'><input
type='submit' name='add' value='Добавить'></td></tr>"
;
print
"</table>";
print
"</form>";
}else{
$question=$_POST['question'];
$answs=$_POST['answs'];
if(
trim($question)==''){
die(
"Вы не ввели вопрос !");
}
$count=0;
for(
$i=(count($answs)-1);$i>=0;$i--){
if(
trim($answs[$i])==''){
$count++;
}
if(
$count==count($answs) || (count($answs)-$count)<2){
die(
'Должно быть как минимум 2 варианта ответа!');
}
}
$conn_id=@mysql_connect("localhost","root","") or die("Ошибка соединения с
сервером БД !"
);
@
mysql_select_db("shockstudio");
$check=@mysql_query("SELECT id FROM `pools` WHERE question='".$question."'",
$conn_id) or die("Ошибка запроса к БД !");
if(@
mysql_num_rows($q)!=0){
die(
"Голосование с таким вопросом уже существует !");
}
unset(
$check);
$q=@mysql_query("INSERT into `pools` VALUES('','".$question."','on')",$conn_id)
or die(
"Ошибка запроса к БД !");
unset(
$q);
$q=@mysql_query("SELECT id FROM `pools` WHERE question='".$question."'",$conn_id)
or die(
"Ошибка во время запроса к серверу !");
$row=@mysql_fetch_array($q);
$id=$row['id'];
unset(
$q,$row);
for(
$i=(count($answs)-1);$i>=0;$i--){
if(
trim($answs[$i])!=''){
$q=@mysql_query("INSERT into `pools_answs` VALUES('','".$id."','".$answs[$i]."',
'')"
,$conn_id) or die("Ошибка запроса к БД !");
}
}
}
?>


Что ж, это и есть функциональная база для добавления голосования в базу данных. Давайте остановимся на этом и рассмотрим всё детальней.

С самого начала мы получаем количество вариантов ответа, которые нужно вывести для редактирования. Мы объявляем переменную `count`, которая в соответствии от существования переменной `count` в QUERY_STRING будет принимать значение или переменной QUERY_STRING (если такая сущестует) и значение по умолчанию, а именно 5. После этого мы работаем над пользовательским интерфейсом, и при этом создаём интересную кнопочку, которая и служит для добавления варианта ответа. При её нажатии значение переменной `count` помещаеться в строку запроса в броузере, и при этом она увеличиваеться на единицу. Вот как всё просто, прям до ужаса. Далее всё просто, и вот мы перешли к обработке полученных из формы данных.

В начале обработки идёт процесс валидации данных. Мы проверям заполнены ли поля формы, а после этого количество вариантов ответа. Для проверки заполненности полей "ответов", мы объявляем переменную $count, которая будет каждый раз увеличиваться, если $i-й элемент массива будет не заполнен.

После, если количество незаполненных полей ($count), будет равно общей сумме вариантов ответа, или их разница будет менее 2-х, то будет возбужденно исключение, которое сообщит пользователю о том, что нужно ввести минимум 2 варианта ответов. На этом проверка данных завершаеться, и мы переходим к валидации данных в БД. Сначала нам нужно проверить, не существует ли уже голосования с таким вопросом, и если существует то возбуждаем ошибку. Если всё же нет, то добавляем данные в таблицу.

Следующим шагом будет получение индификатора (id) текущей записи, для добавления вариантов ответа в таблицу. После того как мы получили ID, мы снова делаем перебор, только теперь уже с иной целью. Сейчас мы будем добавлять каждый i-й элемент массива, при условии что он не пустой, в таблицу для ответов, при этом мы так же добавляем и индификатор голосования к которому будет привязан данных ответ. Ну и в случае успеха, выводим сообщение о том, что всё прошло успешно. Как видите, без учёта некоторых моментов, всё довольно легко. Но это только первый кусочек той большой мозаики общей функциональностию. Сейчас мы переходим к следующей части, которая и будет неким тестом предыдущей, а именно воплотим сам механизм голосования через интерфейс сайта. В контексте данного варианта исполнения, это займёт почти несколько строк, так как нам всего-то навсего нужно обновить поле в одной таблице, и занести данные в другую.

Что ж, вот мой вариант исполнения данной задачи:


<?
if(!isset(
$_POST['vote'])){
print
"<form action='' method='post' name='vote'>";
print
"<table width='400' height='50' align='center'>";
$conn_id=@mysql_connect("localhost","root","") or
die(
"Ошибка соединения с сервером БД !");
@
mysql_select_db("db");
$q=@mysql_query("SELECT * FROM `pools` WHERE status='on'",$conn_id) or
die(
"Ошибка запроса к БД !");
if(@
mysql_num_rows($q)==0){
echo
"Голосования не найдены !";
}else{
$id=mt_rand(1,@mysql_num_rows($q));
unset(
$q);
$q=@mysql_query("SELECT * FROM `pools` WHERE id='".$id."'",$conn_id) or
die(
"Ошибка запроса к БД !");
$row=@mysql_fetch_array($q);
print
"<tr><Td colspan='2'>Q: ".$row['question']."</td>
</tr>"
;
unset(
$q);
$vote_check=@mysql_query("SELECT id FROM `alredy_vote` WHERE ip='".
$_SERVER['REMOTE_ADDR']."'",$conn_id) or die("Ошибка запроса к БД !");
$q=@mysql_query("SELECT id,value FROM `pools_answs` WHERE vote_id='".
$id."'",$conn_id) or die("Ошибка запроса к БД !");
if(@
mysql_num_rows($q)==0){
die(
"Вопросы не найдены !");
}else{
while(
$row=@mysql_fetch_array($q)){
$row2=@mysql_fetch_array($q2);
if(@
mysql_num_rows($vote_check)!=0){
$q2=@mysql_query("SELECT count FROM `pools_answs` WHERE id='".$row['id']."'",
$conn_id) or die("Ошибка запроса к БД !");
print
"<tr><td>".$row['value']."</td><td>".
$row2['count']."</td></tr>";
}else{
print
"<tr><td>".$row['value']."</td><td><input
type='radio' name='answer' value='"
.$row['id']."'></td></tr>";
print
"<input type='hidden' name='id' value='".$id."'>";
print
"<tr><td colspan='2'><input type='submit' name='vote'
value='Проголосовать'></td></tr>"
;
}
}
}
}
print
"</table>";
print
"</form>";
@
mysql_close($conn_id);
}else{
$id=$_POST['id'];
$answer=$_POST['answer'];
$conn_id=@mysql_connect("localhost","root","")
or die(
"Ошибка во время запроса к серверу !");
@
mysql_select_db("db");
$q=@mysql_query("SELECT id FROM `aredy_vote` WHERE ip='".
$_SERVER['REMOTE_ADDR']."'",$conn_id)
or die(
"Ошибка во время запроса к серверу !");
if(@
mysql_num_rows($q)!=0){
print
"Вы уже участвовали в данном голосовании !";
}else{
$q=@mysql_query("INSERT into `alredy_vote` VALUES('','".$id."','".
$_SERVER['REMOTE_ADDR']."')",$conn_id) or die("Ошибка запроса к БД !");
unset(
$q);
$q=@mysql_query("UPDATE `pools_answs` SER count=count+1 WHERE id='".$id.
"' AND vote_id='".$_POST['answer']."'",$conn_id) or die("Ошибка запроса к БД !");
print
"Ваш голос учтён. Спасибо за участие !!";
}
@
mysql_close($conn_id);
}
?>




Источник: http://www.codenet.ru/
Категория: php | Добавил: freeone (19.05.2007) | Автор: Карпенко Кирилл
Просмотров: 531 | Рейтинг: 0.0 |

Всего комментариев: 0
Имя *:
Email *:
Код *:

Copyright Информационные технологии © 2006