Středoškolská odborná činnost 2007/2008 Obor 18 – Informatika
Naprogramování webové ankety pomocí jazyka PHP a databáze MySQL
Autor:
Jan Tvrdík
Ročník:
kvinta
Škola:
Cyrilometodějské gymnázium, Komenského 17, Prostějov 796 01
Místo zpracování:
Prostějov
Konzultant práce:
Mgr. Ivana Matyášková
Vedoucí práce:
Mgr. Ivana Matyášková
Prohlašuji tímto, že jsem soutěžní práci vypracoval samostatně pod vedením Mgr. Ivany Matyáškové a uvedl v seznamu literatury veškerou použitou literaturu a další informační zdroje včetně internetu. V Prostějově dne 29. 3. 2008
vlastnoruční podpis autora
2
Anotace Cílem práce bylo naprogramovat modul webové ankety, který by neomezoval pokročilé tvůrce webu a umožnil jim rychle a snadno dosáhnout požadovaného cíle. Zatímco začátečník si vystačí s nějakou free anketou1, pokročilý tvůrce webu chce více. Nechce být ničím omezován a chce mít maximální možnou kontrolou nad tím, co se děje. Modul, který jsem naprogramoval, se snaží těmto cílům co nejvíce přiblížit. Za pokročilého tvůrce webu lze považovat toho, kdo absolvoval tutoriál na linuxsoftu2 nebo má ekvivalentní znalosti (nebo samozřejmě vyšší). Neměla by mu činit problém práce s MySQL a s následným zpracováním výsledků na straně PHP. Znalost HTML považuji za samozřejmost. Aplikaci může použít i méně pokročilý tvůrce webu, ale nedokáže z ní vytěžit to, co pokročilý, a v některých případech by pro něj bylo lepší využít výše zmiňovaných služeb třetích stran.
1 2
Např. český služba http://blueboard.cz/sluzby-anketa Nejlepší český PHP tutoriál – http://www.linuxsoft.cz/php/
3
Obsah Anotace ................................................................................................................... 3 Obsah ...................................................................................................................... 4 1
Úvod................................................................................................................ 5
2
Metodika ......................................................................................................... 6
3
Vysvětlení základních pojmů ............................................................................ 7 3.1
Stručné vysvětlení komunikace na internetu ................................................... 7
3.1.1 Příklad http požadavku ................................................................................. 7 3.1.2 Příklad http odpovědi.................................................................................... 7 4
Instalace modulu ............................................................................................. 8
5
Teoretická část................................................................................................. 9 5.1
Požadavky na můj anketní modul..................................................................... 9
5.2
Rozvržení architektury ...................................................................................... 9
5.2.1 Struktura dat v databázi .............................................................................. 10 5.2.2 Rozdělení úkolů skriptům ........................................................................... 14 5.2.3 Struktura administračního rozhraní ............................................................ 14 6
7
Praktická část ................................................................................................ 15 6.1
Hlavní konfigurační soubor (config.php) ........................................................ 15
6.2
Výpis ankety (anketa.php) .............................................................................. 18
6.3
Hlasovací skript (hlasuj.php) ........................................................................... 21
Ukázky použití ............................................................................................... 24 7.1
Tvorba ankety ................................................................................................. 24
7.2
Tvorba vlastní šablony .................................................................................... 24
7.3
Vložení vytvořené ankety do stránky ............................................................. 25
8
Závěr ............................................................................................................. 26
9
Použité zdroje ................................................................................................ 27 4
1 Úvod Ve svých 12-ti letech jsem se poprvé začal zabývat tvorbou webových stránek. Toto odvětví mě natolik zaujalo, že jsem se jím začal zabývat hlouběji a hlouběji. V současné době obstojně zvládám (X)HTML, CSS, PHP a základy JavaScriptu. Vím, co je to validita, sémantika, přístupnost, typografie, SEO i SEM. Internet je věc, která k 21. století neodmyslitelně patří. Téměř každý mladý člověk ve vyspělých státech světa má k němu přístup. Již dávno to není jen výsada hrstky nadšenců. Nyní může ovlivnit obsah internetu úplně každý. Této možnosti využívá stále více a více lidí a mít vlastní stránky či alespoň blog už je v současné době běžná záležitost. Pokud máte vlastní stránky, obvykle chcete dát čtenářům možnost na obsah reagovat. Jedním z nejjednodušších a nejpoužívanějších řešení je bezpochyby anketa. Existuje několik způsobů, jak dostat anketu na stránky. První, nejjednodušší způsob (určený hlavně začínajícím tvůrcům webu) je využít některé ze zdarma nabízených služeb na internetu. Jak už to tak ale bývá, co je zadarmo, má své omezení. Upravit vzhled ankety, aby ladil s ostatním obsahem vašeho webu, může být poměrně tvrdý oříšek. Druhý způsob, který nám umožní dokonalé přizpůsobení ankety našim představám, je naprogramovat si anketu sám. To je ale poměrně pracné a časově náročné a hlavně ne každý to zvládne. Já se proto pokusím představit řešení, které je kompromisem obou výše uvedených možností. Modul, který jsem naprogramoval je navržen tak, aby ho dokázal použít každý mírně pokročilý programátor webových stránek, a vzhled takto vytvořené ankety lze pomocí šablon takřka libovolně modifikovat.
5
2
Metodika Anketa je prvek dynamický, a proto dynamické musí být i technologie pro její tvorbu
použité. Jako nejvhodnější se mi jeví jazyk PHP. Pro ukládání dat jsem zvolil databázi MySQL, která se s PHP výborně rozumí. Použití (X)HTML3, CSS4 a případně JavaScriptu5 považuji za nezbytnou samozřejmost. Celá aplikace byla naprogramována ve výborném, zdarma dostupném editoru PSPad6 4.5.2. Testovací server byl složen z Apache7 2.2.4, PHP8 5.2.3 a MySQL9 5.0.45. Testována byla v internetovém prohlížeči Firefox 2.0 s rozšířením Web Developer10 a Firebug11, Opera 9.23, Internet Explorer 6, Internet Explorer 7 a Konqueror12.
3
Zkratka anglického extensible hypertext markup language – „rozšiřitelný hypertextový značkovací jazyk“ 4 Zkratka pro anglický název Cascading Style Sheets, česky tabulky kaskádových stylů 5 Multiplatformní, objektově orientovaný skriptovací jazyk používaný při tvorbě webových stránek 6 Zdarma ke stažení z http://www.pspad.com/cz/ 7 Zdarma ke stažení z http://apache.org/ 8 Zdarma ke stažení z http://php.net/ 9 Zdarma ke stažení z http://mysql.com/ 10 Zdarma ke stažení z http://chrispederick.com/work/web-developer/ 11 Zdarma ke stažení z http://getfirebug.com/ 12 Internetový prohlížeč pro Linux zdarma ke stažení z http://konqueror.org/
6
3 Vysvětlení základních pojmů PHP je skriptovací programovací jazyk používaný především pro tvorbu webových aplikací. Je vyhodnocován na straně serveru (např. Apache) a uživateli je posílán až výsledek. PHP je nezávislé na použitém operačním systému. MySQL je pravděpodobně nejpoužívanější databázový systém na webu. Syntaxe vychází z obecného SQL jazyka. Stejně jako PHP je nezávislá na použitém operačním systému. Apache je webový server.
3.1 Stručné vysvětlení komunikace na internetu Komunikace mezi uživatelem (internetovým prohlížečem) a vzdáleným serverem probíhá pomocí protokolu http13. Prohlížeč pošle požadavek webovému serveru. Ten jej zpracuje (např. pokud se jedná o PHP skript, tak jej předá interpretu PHP) a společně s odpovědní hlavičkou pošle výsledek zpět prohlížeči. Prohlížeč si odpověď přečte a zobrazí výsledek uživateli.
3.1.1 Příklad http požadavku GET / HTTP/1.1 Host: example.com User-Agent: Opera/9.02 (Windows NT 5.0; U; en) Accept: application/xhtml+xml,text/html;q=0.9,image/png Accept-Charset: windows-1250,utf-8;q=0.7,*;q=0.7 3.1.2 Příklad http odpovědi HTTP/1.x 200 OK Date: Sat, 29 Mar 2008 18:38:39 GMT Server: Apache/2.2.3 (CentOS) Content-Length: 438 Connection: close Content-Type: text/html; charset=UTF-8
13
Hypertext Transfer Protocol
7
4 Instalace modulu Instalace modulu probíhá pomocí skriptu „instalace.php“. Pokud modul není nainstalován, tak skript „index.php“ automaticky na instalaci přesměruje. Celý proces trvá velmi krátce a spočívá v zadání několika nezbytných informací:
Položka
Vysvětlení
Host Přihlašovací jméno Přihlašovací heslo Jméno databáze
Informace přidělená poskytovatelem hostingu Jméno k připojení k databázi Heslo k připojení k databázi Jméno používané databáze14
Tabulka anketa Tabulka odpovědí Tabulka hlasů Tabulka šablon
Heslo do administrace Heslo znovu
14
Jméno tabulky obsahující obecné informace o anketách Jméno tabulky obsahující možné odpovědi na anketní otázku Jméno tabulky obsahující záznamy všech hlasování Jméno tabulky obsahující informace o šablonách Heslo používané k přihlášení do administrace anket Stejné jako předchozí, slouží pro kontrolu správnosti
Skript předpokládá již existující databázi
8
Obvyklé hodnoty pro „domácí server“ „Localhost“ „root“ „“ libovolné „ankety“ „odpovedi“ „hlasy“ „sablony“
Libovolné Stejné jako předchozí
5 Teoretická část 5.1 Požadavky na můj anketní modul První a velmi podstatnou věcí, kterou je dobré znát, než se pustím do vlastního programování, je vědět, co chceme naprogramovat. V mém případě půjde o modul webové ankety. V praxi to znamená, že musí být snadno přizpůsobitelný. Proto bude vlastní anketa vykreslováno pomocí šablony, kterou si bude moci uživatel vytvořit a následně upravit. O samotný chod ankety se bude starat jen minimum skriptů. Většina z nich se bude starat o uživatelské rozhraní, které by mělo dokázat: Vytvořit novou anketu Upravit existující anketu Smazat existující anketu Vytvořit novou šablonu Upravit existující šablonu Smazat existující šablonu Celé uživatelské rozhraní musí být samozřejmě chráněné heslem, aby nějaký nudící se uživatel nezačal ankety mazat. Jednou z dalších věcí, které nesmíme opomenout, je ochrana proti opakovanému hlasování (viz 6.3).
5.2 Rozvržení architektury Většina dat bude ukládána v databázích (jen šablony budou ukládány do adresáře, protože půjde o PHP skripty). Konkrétně nám půjde o anketní otázku možné odpovědi na danou otázku nastavení ankety – doba blokace a použitá šablona hlasy – kdy jaká IP adresa hlasovala v jaké anketě jméno, popis a adresář (ve kterém je šablona uložena) šablony
9
5.2.1 Struktura dat v databázi 5.2.1.1 Tabulka ankety Tabulka ankety obsahuje základní informace o každé anketě. Ke každé anketě náleží právě jeden řádek. idankety jednoznačný identifikátor každé ankety hojně používaný ve většině skriptů otazka otázka pokládaná v anketě ochrana počet sekund, po které nebude možné znovu hlasovat v dané anketě z jedné IP adresy sablona identifikátor šablony (v tabulce sablony), kterou daná anketa používá datum obsahuje časové razítko s datem poslední modifikace ankety
Sloupec idankety otazka ochrana sablona datum
Typ smallint(3) varchar(255) bigint(20 smallint(3) int(12)
Nulový ne ne ne ano ne
Výchozí
1
10
Extra auto_increment
Indexy primární klíč
5.2.1.2 Tabulka odpovedi Tabulky odpovedi obsahuje seznam všech možných odpovědí na všechny ankety. Ke každé anketě náleží alespoň dva řádky. id jednoznačný identifikátor dané odpovědi anketa určuje, ke které anketě daná odpověď patří odpoved jedna z možností, jak odpovědět v dané anketě hlasu počet lidí, kteří zvolili danou odpověď
Sloupec id anketa odpoved hlasu
Typ smallint(6) smallint(3) varchar(255) mediumint(9)
Nulový ne ne ne ano
Výchozí
0
11
Extra auto_increment
Indexy primární klíč
5.2.1.3 Tabulka hlasy Tabulka hlasy obsahuje jeden řádek pro každé hlasování, takže na jednu anketu připadá neomezený počet řádků. idhlasu jednoznačný identifikátor každého hlasu idankety jednoznačně přiřazuje každý hlas k jedné anketě ip IP adresa, ze které hlasování proběhlo cas obsahuje přesný čas hlasování ve formě časového razítka
Sloupec idhlasu idankety ip cas
Typ int(10) smallint(3) varchar(30) int(12)
Nulový ne ne ne ne
Výchozí
Extra auto_increment
Indexy primární klíč unikátní klíč
12
5.2.1.4 Tabulka sablony Tabulka sablony obsahuje základní informace o šablonách. Obsahuje jméno, popis a jméno adresáře, ve kterém je šablona uložena. idsablony obsahuje jednoznačný identifikátor dané šablony jmeno obsahuje slovní pojmenování šablony adresar obsahuje jméno adresáře, ve kterém je šablona uložena; povoleny jsou pouze písmena anglické abecedy a čísla
Sloupec idsablony jmeno adresar popis
Typ smallint(2) varchar(50) varchar(50) varchar(255)
Nulový ne ne ne ano
Výchozí
Extra auto_increment
Indexy primární klíč unikátní klíč
nic
13
5.2.2 Rozdělení úkolů skriptům Nyní se stručně podíváme na funkce některých důležitých skriptů. config.php skript načítaný všemi ostatními skripty. Má na starost nastavení sessions, připojení k databázi a definici spousty základních funkcí (více o souboru config.php viz 6.1) index.php stará se o přihlašování anketa.php po přijetí parametru idankety vekreslí požadovanou anketu (více viz 6.2) hlasuj.php má na starost provedení vlastního hlasování (více viz 6.3) nova-anketa.php, upravit-anketu.php, smazat-anketu.php skripty starající se o vkládání, úpravu a smazání ankety nova-sablona.php, upravit-sablonu.php, smazat-sablonu.php skripty starající se o vkládání, úpravu a smazání šablony instalace.php jediný skript, který nenačítá config.php. Je naprosto nezávislý na ostatních skriptech a staré se o prvotní instalaci anketního modulu (vytvoří tabulky a config.php). 5.2.3 Struktura administračního rozhraní Při vstupu do administračního rozhraní jste
uvítání
velmi
jednoduchým
přihlašovacím dialogem, který naznačuje jednoduchost celého rozhraní. Přihlášení je odesláno skriptu prihlas.php (u výkonných skriptů PHP používám imperativ15). Pokud zadáte heslo správně, jste přesměrování na seznam anket. Pokud ho zadáte špatně, jste přesměrování na info.php a následně zpět na index.php. Aby se zabránilo opakovanému posílání dat (při obnovení stránky) je celá aplikace napsána metodou: Zobrazení rozhraní => výkonný skript PHP => přesměrování na info.php nebo na stránku, kam si uživatel přeje směřovat.
15
rozkazovací způsob
14
6 Praktická část Nyní se detailněji podíváme na některé důležité skripty.
6.1 Hlavní konfigurační soubor (config.php) První a také nejpoužívanější skript, na který se detailněji podíváme, je config.php. Jeho úkolem je spustit podporu sessions (řádek 2), připojit se k databázi (řádek 7 – 25) a definovat pár funkcí (řádek 27 – 90). Nastavení sessions je velmi jednoduché, takže ho není třeba dále vysvětlovat. Připojení k databázi už je věc podstatně složitější. Nejprve jsou všechny přihlašovací hodnoty uloženy do proměnných. Pokud je chceme změnit, není nic jednoduššího, než skript otevřít a hodnoty proměnných upravit. Za standardních podmínek by vše mělo proběhnout bez problému, ale je potřeba počítat i s možností náhlého výpadku databáze. V takovém případě je celý běh skriptu ukončen a vypsána informační hláška (Nemá smysl pokračovat, protože všechny skripty ke svému běhu databázi potřebují.). Pokud připojení k databázi proběhne bez problému, jsou nadefinována jména tabulek, která jsou využívány všemi skripty při práci s databází. Pokud by se pro názvy tabulek nepoužívaly proměnné (byly by nastaveny ve skriptech natvrdo), byla by pak jejich pozdější změna velmi náročná. Proto je vhodné používat pro názvy tabulek proměnné už od začátku. 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017
" . mysql_error()); if(!mysql_select_db("$SQL_DBNAME",$spojeni))
15
018 019 020 021 022 023 024 025
die("Nepodařilo se zvolit DB:
" . mysql_error()); mysql_query("SET NAMES utf8"); //kvůli problémům s kódováním //Definice tabulek define("ANKETY","ankety"); define("ODPOVEDI","odpovedi"); define("HLASY","hlasy"); define("SABLONY","sablony");
Další velmi podstatnou věcí, o kterou se config.php stará, je definice často používaných funkcí. Pokud bychom je chtěli změnit, stačí nám provést změnu na jednom místě a tím se vše opět usnadní. Jednou z velmi často používaných funkcí (vyplývá z rozvržení architektury) je přesměrování. Podle specifikace, by se mělo přesměrovávat absolutním URL (funguje i relativní). V PHP naštěstí není problém si napsat funkci, která nám převede relativní URL na absolutní.
027 //Definice funkcí 028 function VratAbsolitniUrl($url) 029 { 030 //kontrola, jestli už url není absolutní 031 if(ereg("^(http://)", $url)) 032 return $url; 033 034 //případné doplnění chybějícího úvodního lomítka 035 if(!ereg("^/", $url)) 036 $url = "/$url"; 037 038 $cesta = substr($_SERVER["SCRIPT_NAME"], 0, strrpos($_SERVER["SCRIPT_N AME"],"/")) . $url; 039 return "http://" . $_SERVER["SERVER_NAME"] . $cesta;
040 041 042 043 044 045 046 047
} function presmeruj($cil) { header("Location: " . VratAbsolitniUrl($cil)); exit(); }
Velmi často je také potřeba informovat uživatele o průběhu akce. K tomuto účelu slouží následující dvě funkce a skript info.php. Můžete si také všimnout, že funkce se
16
využívají vzájemně i v tomto skriptu. Funkce ZobrazInfo používá funkci VratAbsolitniUrl a funkci presmeruj. 048 049 050 051 052 053 054 055 056 057 058 059 060
//Zobrazí text na aktuální stránce function ZobrazZpravu($text, $color = false) { if($color) $style = " style=\"color: $color;\""; else $style = NULL; echo " echo " echo "
\n"; $text\n";
\n";
}
//Zobrazí text za pomocí info.php function ZobrazInfo($zprava, $reload_url = false, $reload_time = false, $b arva = false) 061 {
062 063
if($zprava) $_SESSION["zprava"] = $zprava; if($reload_url) $_SESSION["reload_url"] = VratAbsolitniUrl($reload_url );
064 065 066 067 }
if($reload_time) $_SESSION["reload_time"] = $reload_time; if($barva) $_SESSION["barva"] = $barva; presmeruj("/info.php");
Z hlediska bezpečnosti hrají velmi důležitou roli následující funkce, které kontrolují přihlášení uživatele. 069 070 071 072 073 074 075 076 077 078 079
function JePrihlasen() { return isset($_SESSION["prihlasen"]); } function VyzadovatPrihlaseni() { if(JePrihlasen()) return true; ZobrazInfo("Tato stránka vyžaduje přihlášení","/index.php"); }
17
Poslední funkcí obsaženou v tomto skriptu je funkce ZkontrolujDotaz, která je pravděpodobně nejpoužívanější funkce vůbec, neboť je volána po každém SQL dotazu. 081 082 083 084 085 086 087 088 089 090 091
function ZkontrolujDotaz($dotaz) { global $cislo_dotazu, $chyba; $cislo_dotazu = isset($cislo_dotazu) ? $cislo_dotazu + 1 : 1; if($dotaz) return true; $chyba = "Došlo k chybě SQL dotazu #$cislo_dotazu"; return false; } ?>
6.2 Výpis ankety (anketa.php) Všimněte si, že config.php je načítán pomocí funkce require_once. Ta se postará hned o dvě věci. Zaprvé - pokud by se config.php z nějakých důvodu nepodařilo načíst, běh skriptu se zastaví. Zadruhé – pokud by se z nějakých nepochopitelných důvodů vyskytl tento řádek v kódu vícekrát, je načten pouze jednou, čímž se předejte chybě (function is already defined…).
Skript anketa.php slouží k vykreslení ankety. Aby byl anketu schopen vykreslit, musí být volán s parametrem idankety (např. anketa.php?idankety=1). 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019
//počáteční inicializace
$max = strlen($znaky) - 1; for($i = 0; $i < $delka; $i++) $retezec .= $znaky[rand(0, $max)]; return $retezec;
18
020 }
První potřebnou věcí je načíst z databáze informace o dané anketě. Poté stačí zkontrolovat, zda načtení proběhlo úspěšně a zda požadovaná anketa vůbec existuje. 022 do 023 { 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043
//načtení ankety z databáze $dotaz = mysql_query(" SELECT a.otazka, a.datum, o.id, o.odpoved, o.hlasu, s.adresar FROM `".ANKETY."` AS a JOIN `".ODPOVEDI."` AS o ON a.idankety = o.anketa JOIN `".SABLONY."` as s ON a.sablona = s.idsablony WHERE idankety = $idankety ORDER BY o.id",$spojeni); //kontrola správnosti průběhu dotazu if(!ZkontrolujDotaz($dotaz)) break; //kontrola existence ankety if(mysql_num_rows($dotaz) < 1) { ZobrazZpravu("Anketa s id = $idankety neexistuje."); break; }
Další krok je poměrně náročný. Je potřeba zpracovat data z databáze tak, aby byla dále zpracovatelná. Všechny odpovědi uložíme do pole odpovědi. Každá odpověď přitom bude tvořena dalším polem obsahujícím identifikátor odpovědi, vlastní odpověď a počet hlasů pro danou odpověď. Později ještě doplníme, jak bude mít daná odpověď dlouhý graf a jakým kódem bude možné pro ni hlasovat (více o hlasovacím kódu viz 6.3) 045 046 047 048 049 050 051 052 053 054
//převedení dat načtených z databáze do proměných a polí while($anketa = mysql_fetch_assoc($dotaz)) { if(!isset($otazka)) $otazka = $anketa["otazka"]; if(!isset($datum)) $datum = $anketa["datum"]; if(!isset($sablona)) $sablona = $anketa["adresar"]; $odpovedi[] = array( "id"
=> $anketa["id"],
"odpoved"
=> $anketa["odpoved"],
"pocet_hlasu" => $anketa["hlasu"]
19
055 056 057 058 059
); } //zkusíme načíst individuální nastavení ankety (ze šablony) if(file_exists("./sablony/$sablona/nastaveni.php")) //pokud nastavení exi stuje,
060 061
@include("./sablony/$sablona/nastaveni.php"); //tak ho načteme if(!isset($sirka_ankety)) $sirka_ankety = 150; //neproběhlali inicializace, tak načteme výchozí hodnoty
062 063 064 065 066 067 068 069 070 071
if(!isset($minimalni_pocet_pixelu)) $minimalni_pocet_pixelu = 1; //spočítáme celkový a nejvyšší počet hlasů $celkem_hlasu = 0; $nejvic_hlasu = 0; foreach($odpovedi as $odpoved) { $celkem_hlasu += $odpoved["pocet_hlasu"]; if($odpoved["pocet_hlasu"] > $nejvic_hlasu) $nejvic_hlasu = $odpoved[ "pocet_hlasu"];
072 073 074 075 076 077 078 079 080 081 082 083 084 085
} //ještě se nehlasovalo if($celkem_hlasu < 1) { $_SESSION["kod"] = array(); foreach($odpovedi as $klic => $odpoved) { $odpovedi[$klic]["procent"] = 0; $odpovedi[$klic]["pixelu"] = $minimalni_pocet_pixelu; //sestavíme kontrolní kód $kontrolni_kod = nahodny(); $_SESSION["kod"][$kontrolni_kod] = $odpoved["id"];
//uložíme ho
do session
086
$odpovedi[$klic]["kod"] = $kontrolni_kod; //a přidáme jako parame tr odpovědi
087 088 089 090 091 092 093 094 095
} } //už se hlasovalo else { //spočítáme parametry grafu foreach($odpovedi as $klic => $odpoved) { $procent = round($odpoved["pocet_hlasu"] / $celkem_hlasu * 100,2) ;
20
096
$pixelu = round($odpoved["pocet_hlasu"] / $nejvic_hlasu * $sirka_ ankety);
097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
//alternativní algoritmus na výpočet počtu pixelů //$pixelu = round($odpoved["pocet_hlasu"] / $nejvic_hlasu * ($sir ka_ankety - $minimalni_pocet_pixelu)) + $minimalni_pocet_pixelu; $odpovedi[$klic]["procent"] = $procent; $odpovedi[$klic]["pixelu"] = $pixelu > $minimalni_pocet_pixelu ? $pixelu : $minimalni_pocet_pixelu; $kontrolni_kod = nahodny(); $_SESSION["kod"][$kontrolni_kod] = $odpoved["id"]; $odpovedi[$klic]["kod"] = $kontrolni_kod; } } //načteme šablonu, která se postará o vykreslení include("./sablony/$sablona/$sablona.php"); } while(false); if(isset($chyba)) echo $chyba; ?>
6.3 Hlasovací skript (hlasuj.php) Úkolem tohoto skriptu je přijmout hlasovací kód a identifikátor ankety. Pokud přijmutí proběhne v pořádku, pak se zkontroluje platnost hlasovacího kódu a jestli uživatel může hlasovat.
Bezpečnost hlasování Aby výsledky hlasování měly nějakou vypovídací hodnotu, musí být zabráněno jejich manipulaci. Prvním základním bezpečnostním prvkem je zabránění opakovaného hlasování. To se v současné době řeší nejčastěji přes kontrolu IP adresy. Samotná ochrana proti opakovanému hlasování ale pro bezpečnost nestačí. Pokud se hlasování řešení pomocí metody GET, prvním nápadem může být hlasovací URL ve tvaru „hlasuj.php?idankety=1&odpoved=2“. Problémem tohoto řešení je, že hlasovací URL je statické. K manipulaci ankety pak stačí projít pár internetových fór s vysokou návštěvností a povoleným tagem img a vložit obrázek:
Každý návštěvník, kterému se zobrazí váš příspěvek, bude nevědomě hlasovat v anketě. Tento problém jsem vyřešil přidělením nestatického (náhodně generovaného) kontrolního kódu (každé odpovědi jeden). Výsledné hlasovací URL je ve tvaru: hlasuj.php?kod=f600wopagmlz&anketa=1 , kde hlasovací kód je pro každé načtení ankety jiný. 001
21
004 do 005 { 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030
//situace, kdy při hlasování metodou post nevyberou žádnou možnost if(isset($_POST["anketa"]) && !isset($_POST["kod"])) { $id_ankety = $_POST["anketa"]; break; } //kontrola příjmu proměných if(!isset($_REQUEST["kod"],$_REQUEST["anketa"])) { exit("Neplatný požadavek"); } $id_ankety = $_REQUEST["anketa"]; $hlasovaci_kod = $_REQUEST["kod"]; if(!isset($_SESSION["kod"][$hlasovaci_kod])) { unset($_SESSION["kod"]); $chyba = "Neplatný hlasovací kód"; break; } $id_odpovedi = $_SESSION["kod"][$hlasovaci_kod];
//Zjistíme jak dlouhou dobu je nastavena blokace hlasování $dotaz = mysql_query("SELECT ochrana from `".ANKETY."` WHERE idankety = $id_ankety LIMIT 1",$spojeni);
031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049
if(!ZkontrolujDotaz($dotaz)) break; //kontrola existence ankety if(mysql_num_rows($dotaz) < 1) { $chyba = "Anketa neexistuje"; break; } $anketa = mysql_fetch_assoc($dotaz); $blokovat_na = $anketa["ochrana"]; $blokovat_do = time() + $anketa["ochrana"]; //Zkontrolujeme, jestli může uživatel hlasovat //1.test - kontrola cookies if(isset($_COOKIE["anketa_$id_ankety"])) { if(($_COOKIE["anketa_$id_ankety"] + $blokovat_na) > time()) {
22
050 051 052 053 054 055 056 057 058
$chyba = "Nemůžete hlasovat opakovaně."; break; } } //2. test - kontrola ip adresy $ip_adresa = $_SERVER["REMOTE_ADDR"]; $dotaz = mysql_query("SELECT cas FROM `".HLASY."` WHERE idankety = $id_ ankety AND ip = '$ip_adresa' AND (cas + $blokovat_na) > ".time(), $spojeni) ;
059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092
if(!ZkontrolujDotaz($dotaz)) break; if(mysql_num_rows($dotaz) > 0) { $chyba = "Nemůžete hlasovat opakovaně."; break; } //může hlasovat => vložíme hlas $dotaz = mysql_query("UPDATE `".ODPOVEDI."` SET hlasu = (hlasu+1) WHERE id = $id_odpovedi AND anketa = $id_ankety LIMIT 1",$spojeni); if(!ZkontrolujDotaz($dotaz)) break; if(mysql_affected_rows() < 1) { $chyba = "Hlasování se nepodařilo."; break; } //nastavíme omezení před dalším hlasovaním //1. Cookie setcookie("anketa_$id_ankety",time(),$blokovat_do); //2. vložení IP adresy do databáze $dotaz = mysql_query("REPLACE `".HLASY."` (idankety, ip, cas) values (' $id_ankety', '$ip_adresa', '".time()."')",$spojeni); if(!ZkontrolujDotaz($dotaz)) break; } while(false); if(isset($chyba)) $_SESSION["chyba"] = $chyba; presmeruj("/anketa.php?idankety=$id_ankety"); ?>
23
7 Ukázky použití 7.1 Tvorba ankety Tvorba ankety spočívá ve vyplnění jednoduchého formuláře. Jediná položka, která by se mohla jevit jako „záhadná“, je doba blokace. Ta určuje dobu v sekundách, po kterou nebude možná znovu hlasovat ze stejné IP adresy.
7.2 Tvorba vlastní šablony Jedna z nejpodstatnějších věcí, které modul umožňuje, je tvorba vlastní šablony. Nejprve vyplníme pár detailů, jako např. jméno šablony a složky, kde bude šablonu umístěna. Mnohem podstatnější ale je správné vyplnění textarey. Ta obsahuje vlastní PHP kód šablony. Automaticky je vložen kód výchozí šablony, který programátorovy naznačí, jak může asi vypadat. K dispozici je asociativní pole $odpovedi, $otazka, $sablona, $sirka_ankety a $_SESSION["chyba"]. Na základě vytvořené šablony může anketa nabýt zcela odlišného vzhledu.
24
7.3 Vložení vytvořené ankety do stránky V seznamu anket si otevřete náhled ankety. Zde klikněte na „vygenerovat (X)HTML kód“. Zkopírujte jej a vložte na požadované místo ve vašich stránkách.
25
8 Závěr Myslím si, že anketní modul, který se mi podařilo naprogramovat, postačuje účelu, pro který byl primárně určen, ale možnosti jeho rozšíření nejsou zdaleka vyčerpány. Jediným větším problémem zůstává použitelnost jen pro alespoň mírně pokročilé tvůrce webových stránek. Proto si myslím, že by bylo velmi zajímavé vytvořit jednoduchý generátor šablon s využitím GD knihovny16, který by umožňoval použití celé aplikace i začínajícím tvůrcům webu.
16
PHP knihovna pro zpracovávání obrázků
26
9 Použité zdroje PHP: Hypertext Preprocessor URL:
[cit. 2007-12-26].
MySQL manuál URL: [cit. 2007-12-26].
Jak ovlivnit libovolné hlasování na iDNES.cz URL: http://myego.cz/item/jak-ovlivnit-libovolne-hlasovani-na-idnes-cz [cit. 07-12-26].
W3Schools Online Web Tutorials URL: [cit. 2007-12-26].
IE Brouci – Chyby / Bugy Internet Explorer URL: [cit. 2007-12-26].
Wikipedia URL: [cit. 2008-03-29].
27