V minulém díle jsem sice slíbil on-line test, ale nakonec jsem se rozhodl, že v tomto díle ukážu, jak udělat něco podobného – jednoduchou anketu (známkování tohoto seriálu) včetně statistiky dosavadních známek. Anketa také obsahuje jednoduchý mechanismus, jak alespoň zčásti zabránit opakovanému hodnocení.

Postup výkladu bude tentokrát opačný než obvykle – od kompletního skriptu k vysvětlení jeho stavebních kamenů. Nejprve tedy dnešní skript:

<html>
<head>
<meta http-equiv=“Content-Type“ content=“text/html; charset=windows-1250″>
<title>PHP – anketa</title>
</head>
<body bgcolor=“#FFFFFF“ text=“#000000″>
<?php
if ($action == „send“): // tady začíná kód, který se vykoná po odeslání formuláře
if (File_Exists („stats.txt“)): // existuje soubor se statistikou?
$fp = FOpen („stats.txt“, „r“);
$stats = Explode („#“, FRead ($fp, 999)); // načteme obsah souboru do pole, jednotlivé části řetězce oddělené znakem # přijdou do jednotlivých buněk
FClose ($fp);
else:
for ($i = 0; $i <= 5; $i++) $stats[$i] = 0; // pokud ještě soubor neexistuje, dáme všude nuly
endif;
if ($stats[0] != $REMOTE_ADDR) $stats[$znamka]++; // pokud tato známka přišla z jiné adresy než ta předchozí, přičteme ji
$stats[0] = $REMOTE_ADDR; // aktualizujeme poslední IP adresu
$hlasu = 0; // celkový počet hlasů (známek)
$suma = 0; // celková suma (počet každé známky násobená její hodnotou)
for ($i = 1; $i <= 5; $i++):
$hlasu += $stats[$i]; // přičteme počet této známky k celkovému počtu
$suma += $i * $stats[$i]; // přičteme počet známky krát její hodnotu k celkové sumě
endfor;
$prumer = (Round (100 * $suma / $hlasu)) / 100; // průměrná známka zaokrouhlená na dvě desetinná místa
$fp = FOpen („stats.txt“, „w“); // uložíme aktuální statistiky
FWrite ($fp, Implode ($stats, „#“));
FClose ($fp);
?>
<center><font face=“Arial CE, Arial“ size=“5″>
Jakou známku byste dali seriálu o PHP? (1… nejlepší, 5 … nejhorší)<br>
Díky za hodnocení. Celkem seriál o PHP oznámkovalo <?php echo $hlasu ?> čtenářů
průměrnou známkou <?php echo $prumer; ?>.
</font></center>
<?php else: ?> // pokud ještě formulář nebyl odeslán, zobrazíme ho
<form action=“anketa.php“ method=“post“>
<center><font face=“Arial CE, Arial“ size=“5″>
Jakou známku byste dali seriálu o PHP? (1… nejlepší, 5 … nejhorší)<br>
<input type=“radio“ name=“znamka“ value=“1″ checked> 1
<input type=“radio“ name=“znamka“ value=“2″> 2
<input type=“radio“ name=“znamka“ value=“3″> 3
<input type=“radio“ name=“znamka“ value=“4″> 4
<input type=“radio“ name=“znamka“ value=“5″> 5
<input type=“hidden“ name=“action“ value=“send“><br>
<input type=“submit“ value=“Oznámkuj!“>
</font></center>
</form>
<?php endif; ?>
</body>
</html>

První důležitá změna oproti předchozím příkladům je to, že formulář i skript, který ho zpracovává, je ve stejném souboru (je to elegantnější řešení). Jak ale skript pozná, zda má zobrazit formulář, nebo výsledek jeho zpracování? Tento problém se řeší pomocí skrytého pole formuláře (v tomto případě se jmenuje action), do kterého se při odeslání uloží nějaká hodnota (send). Skript se pak podle této hodnoty rozhodne, co bude dělat. Hned první instrukce PHP tedy testuje, zda je v proměnné $action hodnota send – v tom případě zpracuje odeslaný formulář. V opačném případě formulář nezpracovává, ale zobrazí. Všimněte si, jak lze dosáhnout úsporného zápisu směsi PHP a HTML, která se má v každé větvi podmínky vykonat, pomocí vyskakování z PHP do HTML a naopak.

Druhá část podmínky (zobrazení formuláře) je poměrně triviální – v poli znamka návštěvník odešle svůj názor na tento seriál. Současně je odesláno zmíněné skryté pole formuláře action.

Zpracování formuláře v první části podmínky je už mnohem zajímavější. Průběžný stav hodnocení si budeme uchovávat v souboru stats.txt. Jde o šest údajů – popořadě IP adresa posledního hodnotícího a počet jedniček, dvojek, trojek, čtyřek a pětek. Jako oddělovač je použit znak #. IP adresa posledního hodnotícího bude sloužit k tomu, abychom znemožnili více hodnocení po sobě ze stejné IP adresy (tato metoda, jak zabránit manipulaci s výsledkem, pochopitelně není úplně ideální, zato však jednoduchá :o).

K tomu, abychom z řetězce s oddělovači vytvořili pole naplněné příslušnými hodnotami, slouží funkce Explode, která má dva parametry. První parametr je oddělovač (v tomto případě tedy „#“), druhý parametr je řetězec, který chceme rozdělit. Výsledkem příkazu $pole = Explode („:“, „Petr:Pavel:Karel“) by tedy bylo tříprvkové pole – v $pole[0] by byl řetězec Petr, v $pole[1] Pavel, v $pole[2] Karel.

Inverzní funkcí k Explode je Implode. Ta má opět dva parametry, tentokrát je však oddělovač jako druhý, první je pole, které chceme převést na řetězec. Po příkazu Explode v předchozím odstavci tedy můžeme provést $puvodni_retezec = Implode ($pole, „:“) a jsme zase tam, kde jsme začali.

Nyní tedy můžeme za pomoci funkce Explode načíst obsah textového řetězce s daty do pole $stats. Ve $stats[0] je poslední IP adresa, porovnáme ji tedy s IP adresou současnou, která je automaticky k dispozici v proměnné $REMOTE_ADDR, a pokud se adresy liší, hodnocení započítáme. Současně aktualizujeme i poslední zaznamenanou IP adresu.

V další části už jen spočítáme, kolik lidí celkem známkovalo, a vypočteme průměrnou známku. Vše potřebné (tj. dosavadní počet jedniček, dvojek… pětek) máme v proměnných $stats[1] až $stats[5]. Při počítání průměru se nám bude hodit funkce Round, která zaokrouhluje na nejbližší celé číslo. My ovšem budeme zaokrouhlovat na dvě desetinná místa. Postup je jednoduchý – číslo vynásobíme stovkou, zaokrouhlíme a opět stovkou vydělíme. Na závěr jen uložíme aktuální data, k tomu použijeme již popsanou funkci Implode, která údaje z pole převede na řetězec.

Shrnutí anebo co si je třeba pamatovat

  • Formulář i jeho zpracování je často potřeba mít v jednom skriptu – k tomu, kterou akci máme vykonat, můžeme využít skryté pole formuláře.
  • Užitečnými pomocníky jsou funkce Explode a Implode – první převádí řetězec s oddělovači na pole, druhá pole na řetězec s oddělovači.
  • V proměnné $REMOTE_ADDR máme automaticky k dispozici IP adresu identifikující počítač, ze kterého přišel požadavek na stránku.
  • Funkce Round slouží k zaokrouhlení na nejbližší celé číslo.

V dalším díle si předvedeme, jak se v PHP pracuje s datumem a časem – nemáte se čeho bát, je to podstatně jednodušší než v ASP :o). Výklad bude opět veden tradičním směrem, tj. nejprve popíšu funkci a teprve pak ukážu, jak se používá.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět