Sonda na bazie danych
Artykuł opisuje jak zrobić dość rozbudowany skrypt www sondy (ankiety) oparty na relacyjnej bazie danych.
Jako, iż najpopularniejszym językiem server-side jest obecnie PHP, kod zdecydowałem się napisać właśnie
w nim, a dokładniej w wersji 5.
Ponieważ dostawałem wiele pytań od osób nieznających się na programowaniu o sposób wdrożenia skryptu, poświęciłem temu zagadnieniu ostatni punkt artykułu.
Spis treści
1 Możliwości
2 Zapytania SQL
3 Obsługa bazy danych
4 Kod skryptu
5 Rozbudowa
5.1 Komentarze użytkowników
5.2 Dodatkowe pola formularza
6 Dla osób chcących wykorzystać kod
Struktura systemu opiera się o dwie główne tabele w bazie. Są to "pytania" i "odpowiedzi":
Dla przykładu stwórzmy jakąś ankietę:
Skrypt korzysta z relacyjnej bazy danych do przechowywania ankiet i ich wyników. Może wykorzystywać różne bazy danych, zależnie od sterownika; bardzo prosta i elementarna klasa dla bazy MySQL, o jaką ja się opierałem:
Użyte zapytania SQL powinny działać także pod PostgreSQL i SQLite (nie wiem jak inne bazy), w przypadku powyższej klasy wystarczy zmienić nazwy funkcji, np. mysql_query na pg_query. Po więcej odsyłam do manuala PHP. Oczywiście, można też skorzystać z PDO, ADOdb, PEAR::DB, czy - w przypadku MySQL - mysqli.
I w końcu najdłużej wyczekiwana część artykułu, mianowicie kod skryptu sondy. Jest to klasa, dla której interfejs (nie jest on konieczny do działania skryptu) można zaprojektować następująco:
Jak już wspominałem, do działania wymagany jest PHP5, aczkolwiek przepisanie na oficjalnie nierozwijanego już i przestarzałego PHP4 nie jest większym problemem. Aby tego dokonać, należy:
Sam wiem, iż najlepiej się analizuje, czyta i sprawdza działanie kodu pokazanego w całości, aniżeli wiele krótkich listingów z omawianą szczegółowo zasadą działania. Kod jest prosty i posiada najważniejsze komentarze, tak więc raczej nie powinno być niejasności.
Jak teraz tego użyć? Ano najprościej w ten sposób:
Jeśli nie chcemy wyświetlić listy z innymi sondami znajdującymi się w bazie, wystarczy przed wyświetleniem (metoda display) dać:
Domyślnie inne ankiety sortowane są od najnowszej do najstarszej. Aby odwrócić kolejność:
Załóżmy, że plik nazwaliśmy poll.php. Takie wywołanie wyświetli najnowszą sondę. Aby wyświetlić ankietę o id równym 5, należy link sformułować następująco: poll.php?id=5. Jeśli wyjdziemy poza zakres istniejących rekordów w bazie, lub wpiszemy coś innego niż liczbę, skrypt wyświetli stosowny komunikat. Pod tym względem system jest więc idiotoodporny.
Możliwości skryptu w łatwy sposób można poszerzyć. Najprościej stworzyć nową funkcję w powyższej klasie, można też utworzyć klasę dziedziczącą po powyższej.
Oto przykład jak dodać mechanizm komentarzy do każdej z ankiet. Napiszemy tutaj klasę dziedziczącą. Stwórzmy pierw tabelę w bazie danych:
A oto kod wraz ze sposobem użycia:
Wyobraźmy sobie, że chcemy dodać dodatkowe pola do formularza, np. przy głosowaniu spisujemy imię, nazwisko i e-mail respondenta. Tym razem dodamy nową funkcję do klasy Poll. Tworzymy tabelę w bazie:
I dodajemy funkcję:
Tablica $this->new_fields zawiera funkcje, które mają być włączone do formularza HTML ankiety, w tym wypadku trzy dodatkowe pola tekstowe. Musimy dodać przed metodą $this->display naszą funkcję (metodę), tak więc inicjalizacja będzie wyglądać następująco:
Ponieważ dostawałem wiele pytań od osób nieznających się na programowaniu o sposób wdrożenia skryptu, postanowiłem napisać tutaj kilka słów rozjaśnienia. Pierw należy dodać do bazy danych zapytania SQL, jak określono w punkcie "Zapytania SQL" (czyli 2x CREATE TABLE). Jeśli chcemy dodać ankietę, to posłużmy się zapytaniem INSERT, przykład również został wyieniony w owym punkcie. W przypadku bazy MySQL i posiadania popularnego klienta www phpMyAdmin (alternatywnie w PostgreSQL phpPgAdmin) nalezy kliknąć na kwadracik "SQL", wkleić zapytania i je wykonać. Kod PHP składa się z klasy Database (ta przedstawiona przeze mnie jest bardzo prosta i nie oferuje żadnych nowych funkcjonalności, aniżeli byśmy z niej nie korzystali) i klasy Poll (lub jeszcze klas dziedziczących, np. w przykładzie PollComm). Pierw musi znaleźć się klasa Database, następnie Poll, a dopiero potem reszta. Na przykład ankieta z drugiego przykładu "Rozbudowy" może wyglądać tak. W razie wątpliwości, propozycji czy innych pytań proszę śmiało pisać, najlepiej na e-mail. Jeśli zdecydowałeś(aś) się umieścić skrypt na swojej stronie, miłym gestem będzie poinformowanie mnie o tym.
coldpeer (at) gmail.com
coldpeer.jogger.pl
Spis treści
1 Możliwości
2 Zapytania SQL
3 Obsługa bazy danych
4 Kod skryptu
5 Rozbudowa
5.1 Komentarze użytkowników
5.2 Dodatkowe pola formularza
6 Dla osób chcących wykorzystać kod
Możliwości
- Obsługa wielu sond
- Dowolna ilość wariantów odpowiedzi dla poszczególnych ankiet
- Ustalenie od kiedy, do kiedy ma być możliwość głosowania
- Możliwość wstrzymania głosowania w ankiecie
- Ograniczenie wielokrotnego głosowania w danej sondzie przez jednego użytkownika za pomocą ciasteczek
- Wyświetlenie linków do innych sond
- Łączna frekwencja jak i poszczególnych wariantów odpowiedzi, obliczenie procenta danej opcji, przedstawienie wyników na słupkowym wykresie
- Obsługa wielu baz danych
- Łatwa rozbudowa kodu
Zapytania SQL
Struktura systemu opiera się o dwie główne tabele w bazie. Są to "pytania" i "odpowiedzi":
CREATE TABLE poll_questions (
id int NOT NULL PRIMARY KEY AUTO_INCREMENT,
title varchar(255) NOT NULL,
date_add datetime NOT NULL,
date_begin datetime NOT NULL,
date_end datetime NOT NULL,
stop int NOT NULL DEFAULT 0
);
CREATE TABLE poll_answers (
id_answer int NOT NULL PRIMARY KEY AUTO_INCREMENT,
id_poll int NOT NULL,
answer varchar(255) NOT NULL,
votes int NOT NULL DEFAULT 0
);
id int NOT NULL PRIMARY KEY AUTO_INCREMENT,
title varchar(255) NOT NULL,
date_add datetime NOT NULL,
date_begin datetime NOT NULL,
date_end datetime NOT NULL,
stop int NOT NULL DEFAULT 0
);
CREATE TABLE poll_answers (
id_answer int NOT NULL PRIMARY KEY AUTO_INCREMENT,
id_poll int NOT NULL,
answer varchar(255) NOT NULL,
votes int NOT NULL DEFAULT 0
);
Dla przykładu stwórzmy jakąś ankietę:
INSERT INTO poll_questions VALUES(
'',
'Twój ulubiony język programowania?',
now(),
now(),
'2020-03-01',
0
);
INSERT INTO poll_answers VALUES('', 1, 'C/C++', 0);
INSERT INTO poll_answers VALUES('', 1, 'Java', 0);
INSERT INTO poll_answers VALUES('', 1, 'PHP', 0);
INSERT INTO poll_answers VALUES('', 1, 'Python', 0);
INSERT INTO poll_answers VALUES('', 1, 'Inny', 0);
'',
'Twój ulubiony język programowania?',
now(),
now(),
'2020-03-01',
0
);
INSERT INTO poll_answers VALUES('', 1, 'C/C++', 0);
INSERT INTO poll_answers VALUES('', 1, 'Java', 0);
INSERT INTO poll_answers VALUES('', 1, 'PHP', 0);
INSERT INTO poll_answers VALUES('', 1, 'Python', 0);
INSERT INTO poll_answers VALUES('', 1, 'Inny', 0);
Obsługa bazy danych
Skrypt korzysta z relacyjnej bazy danych do przechowywania ankiet i ich wyników. Może wykorzystywać różne bazy danych, zależnie od sterownika; bardzo prosta i elementarna klasa dla bazy MySQL, o jaką ja się opierałem:
class Database {
public function __construct() {
mysql_connect('localhost', 'user', 'password');
mysql_select_db('base_name');
}
public function query($sql) {
return mysql_query($sql);
}
public function numrows($sql) {
return mysql_num_rows($sql);
}
public function fetch($sql) {
return mysql_fetch_array($sql);
}
}
public function __construct() {
mysql_connect('localhost', 'user', 'password');
mysql_select_db('base_name');
}
public function query($sql) {
return mysql_query($sql);
}
public function numrows($sql) {
return mysql_num_rows($sql);
}
public function fetch($sql) {
return mysql_fetch_array($sql);
}
}
Użyte zapytania SQL powinny działać także pod PostgreSQL i SQLite (nie wiem jak inne bazy), w przypadku powyższej klasy wystarczy zmienić nazwy funkcji, np. mysql_query na pg_query. Po więcej odsyłam do manuala PHP. Oczywiście, można też skorzystać z PDO, ADOdb, PEAR::DB, czy - w przypadku MySQL - mysqli.
Kod skryptu
I w końcu najdłużej wyczekiwana część artykułu, mianowicie kod skryptu sondy. Jest to klasa, dla której interfejs (nie jest on konieczny do działania skryptu) można zaprojektować następująco:
interface iPoll {
public function display(); // zwraca caly przeparsowany kod HTML sondy
public function other($id); // inne sondy
}
public function display(); // zwraca caly przeparsowany kod HTML sondy
public function other($id); // inne sondy
}
Jak już wspominałem, do działania wymagany jest PHP5, aczkolwiek przepisanie na oficjalnie nierozwijanego już i przestarzałego PHP4 nie jest większym problemem. Aby tego dokonać, należy:
- pozbyć się wielopoziomowych odwołań do składowych (np. stworzyć zmienną $base = $this->db; i odwoływać się $base->query())
- pozbyć się modifikatorów dostępu, tj. z funkcji usunąć słowa kluczowe public, a we właściwościach zastąpić public na var
- zmienić nazwę konstruktora z __construct na taką, jaką nosi nazwa klasy (Poll)
Sam wiem, iż najlepiej się analizuje, czyta i sprawdza działanie kodu pokazanego w całości, aniżeli wiele krótkich listingów z omawianą szczegółowo zasadą działania. Kod jest prosty i posiada najważniejsze komentarze, tak więc raczej nie powinno być niejasności.
/**
* Description: Advanced poll script written in PHP5 using relational database.
* Author: Jędrzej "Coldpeer" Czarnecki
* E-mail: coldpeer (at) gmail.com
* WWW: http://coldpeer.jogger.pl
* Licensed: GNU GPL v3
* Copyright: (c) 2007
*/
class Poll {
public $db;
public $other = true; // czy pokazywac inne sondy
public $desc_sort = true; // sortowanie innych sond od najnowszych
public $id; // id sondy
public $new_fields = array(); // funkcje z nowy polami do formularza
public $no_add = false; // nie dodawac (np. ktoras z funkcji z $new_fields mowi, ze dane niepoprawne)
public function __construct()
{
$this->db = new Database();
}
public function display()
{
$sql = $this->db->query('SELECT
q.id, q.title, q.date_begin, q.date_end, q.stop,
a.id_answer, a.answer, a.votes,
(SELECT sum(votes) FROM poll_answers WHERE id_poll = q.id GROUP BY id_poll) as sum
FROM
poll_questions as q, poll_answers as a
WHERE
q.id = a.id_poll AND q.id = ' .
(!isset($_GET['id']) ? '(SELECT max(id) FROM poll_questions)' : (int)$_GET['id']));
if($this->db->numrows($sql) > 0)
{
$now = date('Y-m-d');
while($row = $this->db->fetch($sql))
{
if($_POST['vote'] && !$this->no_add)
{
$row['sum']++;
if($row['id_answer'] == $_POST['vote']) $row['votes']++;
}
if(!$b)
{
$this->id = $row['id'];
if($row['stop'] == 1 || $_POST['vote'] && !$this->no_add) $noform = true;
// podstawowe dane o ankiecie
$ret .= '<b>' . $row['title'] . '</b><p />Łącznie oddano głosów: ' . $row['sum'].
'<br />Data rozpoczęcia: ' . $row['date_begin'] .
'<br />Data zakończenia: ' . $row['date_end'];
if($row['date_end'] <= $now) $ret .= '<p />Ankieta się już zakończyła.';
elseif($row['stop'] == 1) $ret .= '<p />Glosowanie w ankiecie zostało wstrzymane.';
$ret .= '<p />';
// wyswietlenie formularza
if(!isset($_COOKIE['poll' . $this->id]) && $row['date_end'] > $now && !$noform)
{
$ret .= '<form action="" method="post">';
foreach($this->new_fields as $v) $ret .= $v;
$form = true;
} elseif(isset($_COOKIE['poll' . $this->id]) && $row['date_end'] > $now && !$noform)
{
$ret .= 'Głosowałeś już w tej sondzie.<p />';
}
// user zaglosowal
if($_POST['vote'] && !$this->no_add)
{
$ret .= 'Twój głos został dodany.<p />';
if(!isset($_COOKIE['poll' . $this->id]))
{
$this->db->query('UPDATE poll_answers SET votes=votes+1 WHERE id_answer='.$_POST['vote']);
setcookie('poll' . $this->id, $this->id, time()+3600 * 3600 * 30); // 22 lata
}
$noform = true;
}
$b = true;
}
// wyswietlenie wariantow odpowiedzi
if($form)
$ret .= '<input type="radio" name="vote" value="' . $row['id_answer'] . '" /> ' .
$row['answer'] . '<br />';
else
{
$ret .= $row['answer'].', ' . $row['votes'] . ' glosow, ' .
($row['sum'] > 0 ? round($row['votes']*100/$row['sum']) : 0) . '% ' .
'<div style="background: red; height: 10px; width: ' .
($row['votes'] == 0 || $row['sum'] == 0 ? 5 : round($row['votes'] * 200 / $row['sum'])) .
'px"></div><br />';
}
}
if($form) $ret .= '<br /><input type="submit" name="submit" value="Głosuj!" /></form>';
if($this->other) $ret .= '<p /><b>Inne sondy</b><p />' . $this->other($this->id);
}
else $ret = 'Nie ma takiej sondy w bazie.';
return $ret;
}
public function other($id)
{
$sql = 'SELECT id, title FROM poll_questions WHERE id <> ' . $id . ' ORDER BY id ' . ($this->desc_sort ? 'DESC' : 'ASC');
$sql = $this->db->query($sql);
if($this->db->numrows($sql) > 0)
{
$ret = '<ul>';
while($row = $this->db->fetch($sql))
$ret .= '<li><a href="' .$_SERVER['PHP_SELF'] . '?id=' . $row['id'] . '">' . $row['title'] . '</a></li>';
return $ret . '</ul>';
}
else return '(brak)';
}
}
* Description: Advanced poll script written in PHP5 using relational database.
* Author: Jędrzej "Coldpeer" Czarnecki
* E-mail: coldpeer (at) gmail.com
* WWW: http://coldpeer.jogger.pl
* Licensed: GNU GPL v3
* Copyright: (c) 2007
*/
class Poll {
public $db;
public $other = true; // czy pokazywac inne sondy
public $desc_sort = true; // sortowanie innych sond od najnowszych
public $id; // id sondy
public $new_fields = array(); // funkcje z nowy polami do formularza
public $no_add = false; // nie dodawac (np. ktoras z funkcji z $new_fields mowi, ze dane niepoprawne)
public function __construct()
{
$this->db = new Database();
}
public function display()
{
$sql = $this->db->query('SELECT
q.id, q.title, q.date_begin, q.date_end, q.stop,
a.id_answer, a.answer, a.votes,
(SELECT sum(votes) FROM poll_answers WHERE id_poll = q.id GROUP BY id_poll) as sum
FROM
poll_questions as q, poll_answers as a
WHERE
q.id = a.id_poll AND q.id = ' .
(!isset($_GET['id']) ? '(SELECT max(id) FROM poll_questions)' : (int)$_GET['id']));
if($this->db->numrows($sql) > 0)
{
$now = date('Y-m-d');
while($row = $this->db->fetch($sql))
{
if($_POST['vote'] && !$this->no_add)
{
$row['sum']++;
if($row['id_answer'] == $_POST['vote']) $row['votes']++;
}
if(!$b)
{
$this->id = $row['id'];
if($row['stop'] == 1 || $_POST['vote'] && !$this->no_add) $noform = true;
// podstawowe dane o ankiecie
$ret .= '<b>' . $row['title'] . '</b><p />Łącznie oddano głosów: ' . $row['sum'].
'<br />Data rozpoczęcia: ' . $row['date_begin'] .
'<br />Data zakończenia: ' . $row['date_end'];
if($row['date_end'] <= $now) $ret .= '<p />Ankieta się już zakończyła.';
elseif($row['stop'] == 1) $ret .= '<p />Glosowanie w ankiecie zostało wstrzymane.';
$ret .= '<p />';
// wyswietlenie formularza
if(!isset($_COOKIE['poll' . $this->id]) && $row['date_end'] > $now && !$noform)
{
$ret .= '<form action="" method="post">';
foreach($this->new_fields as $v) $ret .= $v;
$form = true;
} elseif(isset($_COOKIE['poll' . $this->id]) && $row['date_end'] > $now && !$noform)
{
$ret .= 'Głosowałeś już w tej sondzie.<p />';
}
// user zaglosowal
if($_POST['vote'] && !$this->no_add)
{
$ret .= 'Twój głos został dodany.<p />';
if(!isset($_COOKIE['poll' . $this->id]))
{
$this->db->query('UPDATE poll_answers SET votes=votes+1 WHERE id_answer='.$_POST['vote']);
setcookie('poll' . $this->id, $this->id, time()+3600 * 3600 * 30); // 22 lata
}
$noform = true;
}
$b = true;
}
// wyswietlenie wariantow odpowiedzi
if($form)
$ret .= '<input type="radio" name="vote" value="' . $row['id_answer'] . '" /> ' .
$row['answer'] . '<br />';
else
{
$ret .= $row['answer'].', ' . $row['votes'] . ' glosow, ' .
($row['sum'] > 0 ? round($row['votes']*100/$row['sum']) : 0) . '% ' .
'<div style="background: red; height: 10px; width: ' .
($row['votes'] == 0 || $row['sum'] == 0 ? 5 : round($row['votes'] * 200 / $row['sum'])) .
'px"></div><br />';
}
}
if($form) $ret .= '<br /><input type="submit" name="submit" value="Głosuj!" /></form>';
if($this->other) $ret .= '<p /><b>Inne sondy</b><p />' . $this->other($this->id);
}
else $ret = 'Nie ma takiej sondy w bazie.';
return $ret;
}
public function other($id)
{
$sql = 'SELECT id, title FROM poll_questions WHERE id <> ' . $id . ' ORDER BY id ' . ($this->desc_sort ? 'DESC' : 'ASC');
$sql = $this->db->query($sql);
if($this->db->numrows($sql) > 0)
{
$ret = '<ul>';
while($row = $this->db->fetch($sql))
$ret .= '<li><a href="' .$_SERVER['PHP_SELF'] . '?id=' . $row['id'] . '">' . $row['title'] . '</a></li>';
return $ret . '</ul>';
}
else return '(brak)';
}
}
Jak teraz tego użyć? Ano najprościej w ten sposób:
Jeśli nie chcemy wyświetlić listy z innymi sondami znajdującymi się w bazie, wystarczy przed wyświetleniem (metoda display) dać:
$poll->other = false;
Domyślnie inne ankiety sortowane są od najnowszej do najstarszej. Aby odwrócić kolejność:
$poll->desc_sort = false;
Załóżmy, że plik nazwaliśmy poll.php. Takie wywołanie wyświetli najnowszą sondę. Aby wyświetlić ankietę o id równym 5, należy link sformułować następująco: poll.php?id=5. Jeśli wyjdziemy poza zakres istniejących rekordów w bazie, lub wpiszemy coś innego niż liczbę, skrypt wyświetli stosowny komunikat. Pod tym względem system jest więc idiotoodporny.
Rozbudowa
Możliwości skryptu w łatwy sposób można poszerzyć. Najprościej stworzyć nową funkcję w powyższej klasie, można też utworzyć klasę dziedziczącą po powyższej.
Komentarze użytkowników
Oto przykład jak dodać mechanizm komentarzy do każdej z ankiet. Napiszemy tutaj klasę dziedziczącą. Stwórzmy pierw tabelę w bazie danych:
CREATE TABLE poll_comments (
id int NOT NULL PRIMARY KEY AUTO_INCREMENT,
id_poll int NOT NULL,
date datetime NOT NULL,
nick varchar(30) NOT NULL,
content text NOT NULL
);
id int NOT NULL PRIMARY KEY AUTO_INCREMENT,
id_poll int NOT NULL,
date datetime NOT NULL,
nick varchar(30) NOT NULL,
content text NOT NULL
);
A oto kod wraz ze sposobem użycia:
class PollComm extends Poll {
public function comments()
{
// dodajemy komentarz
if($_POST['send'])
{
if($this->db->query('INSERT INTO poll_comments VALUES("", ' . $this->id . ', now(), "' .
htmlspecialchars($_POST['nick']) . '","' . htmlspecialchars($_POST['content']).'")'))
$ret = 'Komentarz został dodany do bazy.';
else
$ret = 'Wystąpił błąd podczas próby dodania komentarza.';
}
// lista komentarzy
$sql = $this->db->query('SELECT nick, date, content FROM poll_comments WHERE id_poll = ' . $this->id);
$ret .= '<p /><b>Komentarze (' . $this->db->numrows($sql) . ')</b><p />';
if($this->db->numrows($sql) > 0)
{
while($row = $this->db->fetch($sql))
{
$ret .= '<b>' . $row['nick'] . '</b> napisał (' . $row['date'] . '):<br />' . nl2br($row['content']) . '<p />';
}
} else $ret .= '(nie ma jeszcze żadnych komentarzy)';
// wyswietlamy wszystko i formularz
return $ret . '<p /><b>Dodaj komentarz:<b><form action="" method="post">Nick: <input type="text" name="nick" /><br />' .
'<textarea name="content" cols="40" rows="10"></textarea><br /><input type="submit" name="send" value="Wyślij" /></form>';
}
}
$poll = new PollComm;
echo $poll->display();
echo $poll->comments();
public function comments()
{
// dodajemy komentarz
if($_POST['send'])
{
if($this->db->query('INSERT INTO poll_comments VALUES("", ' . $this->id . ', now(), "' .
htmlspecialchars($_POST['nick']) . '","' . htmlspecialchars($_POST['content']).'")'))
$ret = 'Komentarz został dodany do bazy.';
else
$ret = 'Wystąpił błąd podczas próby dodania komentarza.';
}
// lista komentarzy
$sql = $this->db->query('SELECT nick, date, content FROM poll_comments WHERE id_poll = ' . $this->id);
$ret .= '<p /><b>Komentarze (' . $this->db->numrows($sql) . ')</b><p />';
if($this->db->numrows($sql) > 0)
{
while($row = $this->db->fetch($sql))
{
$ret .= '<b>' . $row['nick'] . '</b> napisał (' . $row['date'] . '):<br />' . nl2br($row['content']) . '<p />';
}
} else $ret .= '(nie ma jeszcze żadnych komentarzy)';
// wyswietlamy wszystko i formularz
return $ret . '<p /><b>Dodaj komentarz:<b><form action="" method="post">Nick: <input type="text" name="nick" /><br />' .
'<textarea name="content" cols="40" rows="10"></textarea><br /><input type="submit" name="send" value="Wyślij" /></form>';
}
}
$poll = new PollComm;
echo $poll->display();
echo $poll->comments();
Dodatkowe pola formularza
Wyobraźmy sobie, że chcemy dodać dodatkowe pola do formularza, np. przy głosowaniu spisujemy imię, nazwisko i e-mail respondenta. Tym razem dodamy nową funkcję do klasy Poll. Tworzymy tabelę w bazie:
CREATE TABLE poll_responders (
id int NOT NULL PRIMARY KEY AUTO_INCREMENT ,
id_poll int NOT NULL,
name varchar(20) NOT NULL,
surname varchar(30) NOT NULL,
email varchar(150) NOT NULL
);
id int NOT NULL PRIMARY KEY AUTO_INCREMENT ,
id_poll int NOT NULL,
name varchar(20) NOT NULL,
surname varchar(30) NOT NULL,
email varchar(150) NOT NULL
);
I dodajemy funkcję:
public function responder()
{
$ret = 'Imię: <input type="text" value="' . $_POST['name'] . '" name="name" /><br />'
. 'Nazwisko:<input type="text" value="' . $_POST['surname'] . '" name="surname" /><br />'
. 'E-mail: <input type="text" value="' . $_POST['email'] . '" name="email" /><p />';
if($_POST['submit'])
{
if($_POST['vote'] && $_POST['name'] && $_POST['surname']
&& $_POST['email'] && !isset($_COOKIE['poll' . $this->id]))
{
if(strlen($_POST['name']) > 20 || strlen($_POST['surname']) > 30 || strlen($_POST['email']) > 150)
{
$ret = '<p />Imię nie może być dłuższe niż 20 znaków, nazwisko niż 30, a e-mail niż 150.<p />' . $ret;
$error = true;
}
if(!preg_match("/^([a-zA-Z0-9_'+*$%\^&!\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9:]{2,4})+$/", $_POST['email']))
{
$ret = '<p />Podany adres e-mail jest nieprawidłowy.<p />' . $ret;
$error = true;
}
if($error || !$this->db->query('INSERT INTO poll_responders VALUES("",(SELECT '
. (!isset($_GET['id']) ? 'max(id)' : 'id') .' FROM poll_questions'
. (isset($_GET['id']) ? ' WHERE id = ' . (int)$_GET['id'] : ''). '),"'
. $_POST['name'] . '","' . $_POST['surname'] . '","' . $_POST['email'] . '")'))
$this->no_add = true;
} else{
$this->no_add = true;
$ret = '<p />Muisz wypełnić wszystkie dane<p />' . $ret;
}
}
return $ret;
}
{
$ret = 'Imię: <input type="text" value="' . $_POST['name'] . '" name="name" /><br />'
. 'Nazwisko:<input type="text" value="' . $_POST['surname'] . '" name="surname" /><br />'
. 'E-mail: <input type="text" value="' . $_POST['email'] . '" name="email" /><p />';
if($_POST['submit'])
{
if($_POST['vote'] && $_POST['name'] && $_POST['surname']
&& $_POST['email'] && !isset($_COOKIE['poll' . $this->id]))
{
if(strlen($_POST['name']) > 20 || strlen($_POST['surname']) > 30 || strlen($_POST['email']) > 150)
{
$ret = '<p />Imię nie może być dłuższe niż 20 znaków, nazwisko niż 30, a e-mail niż 150.<p />' . $ret;
$error = true;
}
if(!preg_match("/^([a-zA-Z0-9_'+*$%\^&!\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9:]{2,4})+$/", $_POST['email']))
{
$ret = '<p />Podany adres e-mail jest nieprawidłowy.<p />' . $ret;
$error = true;
}
if($error || !$this->db->query('INSERT INTO poll_responders VALUES("",(SELECT '
. (!isset($_GET['id']) ? 'max(id)' : 'id') .' FROM poll_questions'
. (isset($_GET['id']) ? ' WHERE id = ' . (int)$_GET['id'] : ''). '),"'
. $_POST['name'] . '","' . $_POST['surname'] . '","' . $_POST['email'] . '")'))
$this->no_add = true;
} else{
$this->no_add = true;
$ret = '<p />Muisz wypełnić wszystkie dane<p />' . $ret;
}
}
return $ret;
}
Tablica $this->new_fields zawiera funkcje, które mają być włączone do formularza HTML ankiety, w tym wypadku trzy dodatkowe pola tekstowe. Musimy dodać przed metodą $this->display naszą funkcję (metodę), tak więc inicjalizacja będzie wyglądać następująco:
$poll = new Poll;
$poll->new_fields[] = $poll->responder(); // przy następnych funkcjach analogicznie
echo $poll->display();
$poll->new_fields[] = $poll->responder(); // przy następnych funkcjach analogicznie
echo $poll->display();
Dla osób chcących wykorzystać kod
Ponieważ dostawałem wiele pytań od osób nieznających się na programowaniu o sposób wdrożenia skryptu, postanowiłem napisać tutaj kilka słów rozjaśnienia. Pierw należy dodać do bazy danych zapytania SQL, jak określono w punkcie "Zapytania SQL" (czyli 2x CREATE TABLE). Jeśli chcemy dodać ankietę, to posłużmy się zapytaniem INSERT, przykład również został wyieniony w owym punkcie. W przypadku bazy MySQL i posiadania popularnego klienta www phpMyAdmin (alternatywnie w PostgreSQL phpPgAdmin) nalezy kliknąć na kwadracik "SQL", wkleić zapytania i je wykonać. Kod PHP składa się z klasy Database (ta przedstawiona przeze mnie jest bardzo prosta i nie oferuje żadnych nowych funkcjonalności, aniżeli byśmy z niej nie korzystali) i klasy Poll (lub jeszcze klas dziedziczących, np. w przykładzie PollComm). Pierw musi znaleźć się klasa Database, następnie Poll, a dopiero potem reszta. Na przykład ankieta z drugiego przykładu "Rozbudowy" może wyglądać tak. W razie wątpliwości, propozycji czy innych pytań proszę śmiało pisać, najlepiej na e-mail. Jeśli zdecydowałeś(aś) się umieścić skrypt na swojej stronie, miłym gestem będzie poinformowanie mnie o tym.
październik 2007
Autor artykułu: Jędrzej "Coldpeer" Czarneckicoldpeer (at) gmail.com
coldpeer.jogger.pl



$tresc = formularz();
w warunku skomentowanym w /* WYNIKI/FORMULARZ */ -> /* formularz */ na:
$tresc = formularz() . '<p />' . wyniki();
Ogólnie mówiąc, to i tak wypadałoby go napisać od nowa.