Dnes nßs Φekß poslednφ dφl serißlu, jeho₧ cφlem bylo seznßmit vßs se zßklady tvorby internetov²ch aplikacφ na stran∞ serveru. Na zßv∞r se budeme v∞novat kolßΦk∙m -- v originßle cookies -- co₧ je velice zajφmavß technologie, kterß dala nßzev i dneÜnφmu Φlßnku. Zopakujme si nejprve struΦn∞ na jakΘm principu cookies pracujφ.
Samotn² protokol HTTP je bezstavov² -- pro sta₧enφ ka₧dΘ strßnky se musφ vytvo°it novΘ spojenφ, po kterΘm se obsah strßnky p°enese. Server tedy nevφ, zda danou strßnku posφlß podesßtΘ jednomu u₧ivateli anebo zda strßnku desetkrßt poskytl r∙zn²m u₧ivatel∙m. P°itom na mnoha strßnkßch by Ülo tuto informaci vyu₧φt. Server by monitoroval pohyb u₧ivatele po strßnkßch a na zßklad∞ jeho vyhodnocenφ by u₧ivateli poskytoval personalizovanΘ strßnky -- nap°. se specifickou reklamou Φi informacemi.
V²Üe zmφn∞nΘho nedostatku si byla v∞doma firma Netscape a vytvo°ila proto cookies, kterΘ brzy zaΦaly podporovat i vÜechny dalÜφ v²znamnΘ firmy ve sv²ch prohlφ₧eΦφch. Cookies jsou rozÜφ°enφm protokolu HTTP -- p°idßvajφ do n∞j dv∞ novΘ hlaviΦky.
Prvnφ hlaviΦku Set-Cookie
pou₧φvß server p°i odesφlßnφ
odpov∞di prohlφ₧eΦi. V tΘto hlaviΦce m∙₧e server prohlφ₧eΦi poslat
informace. ZφskanΘ informace si prohlφ₧eΦ ulo₧φ do souboru. Pokud pak
u₧ivatel v budoucnu p°istupuje ke stejnΘmu serveru, prohlφ₧eΦ ulo₧enΘ
informace poÜle zp∞t serveru v hlaviΦce Cookie
. Server na
zßklad∞ obdr₧en²ch informacφ v cookies zjistφ, ₧e u₧ivatel se k serveru
p°ipojil ji₧ d°φve a m∙₧e na to pat°iΦn∞ zareagovat.
Ka₧dß cookie mß svΘ jmΘno a m∙₧eme do nφ ulo₧it hodnotu. Krom∞ toho lze u ka₧dΘ cookie nastavit dobu jejφ platnosti a dalÜφ atributy.
Prßce s cookies je v PHP velice snadnß. K odeslßnφ cookie klientovi
slou₧φ funkce SetCookie()
. Tuto funkci musφme volat jeÜt∞
p°edtφm, ne₧ nßÜ skript generuje n∞jak² v²stup v HTML, proto₧e cookies
jsou souΦßstφ HTTP-hlaviΦek.
Naopak cookies, kterΘ v po₧adavku na nßÜ skript odeslal prohlφ₧eΦ mßme p°φstupnΘ v prom∞nn²ch odpovφdajφcφho jmΘna podobn∞ jako pole formulß°e.
Pou₧itφ cookies si ukß₧eme na jednoduchΘm p°φklad∞ -- vytvo°φme strßnku, kterß ka₧dΘmu u₧ivateli zobrazφ, kolikrßt ji navÜtφvil:
<? if (!IsSet($pocetPristupu)) $pocetPristupu = 0; $pocetPristupu++; SetCookie("pocetPristupu", $pocetPristupu); ?> <HTML> <HEAD> <TITLE>Vφtejte na serveru s podporou kolßΦk∙</TITLE> </HEAD> <BODY> <? if ($pocetPristupu==1): ?> <H1>Vφtejte nov² u₧ivateli</H1> <?else:?> <H1>Ahoj star² brachu -- my u₧ se znßme</H1> Na naÜem serveru jste ji₧ po <?echo $pocetPristupu?>. <?endif?> </BODY> </HTML>Skript nejprve testuje, zda mu prohlφ₧eΦ poslal cookie s nßzvem
pocetPristupu
. Pokud ne, zinicializuje prom∞nnou
$pocetPristupu
. Nßsledn∞ poΦet p°φstup∙ zaktualizujeme a
odeÜleme zp∞t klientovi. Zobrazenß strßnka se liÜφ podle toho, zda
u₧ivatel ke strßnce p°istupuje poprvΘ nebo ji₧ pon∞kolikßtΘ (viz obr. 1
a 2).
Funkce SetCookie
mß i n∞kolik nepovinn²ch parametr∙.
Celkem m∙₧eme pou₧φt Üest nßsledujφcφch parametr∙:
SetCookie(jmΘno, hodnota, platnost, cesta, domΘna, zabezpeΦenφ)Platnost udßvß Φasov² okam₧ik, do kdy je obsah cookie platn². ╚as se udßvß jako poΦet sekund od zaΦßtku 1. ledna 1970. S v²hodou m∙₧eme pou₧φt funkci
Time()
, kter² vracφ aktußlnφ Φas v
tomto formßtu. K nastavenφ cookie s platnostφ jedna hodina (3600 sekund)
m∙₧eme pou₧φt volßnφ:
SetCookie("Kategorie", "obchod", Time()+3600)Pomocφ parametr∙ cesta a domΘna m∙₧eme rozÜφ°it platnost cookie. Normßln∞ je cookie platnß -- je zasφlßna prohlφ₧eΦem zp∞t serveru -- pouze pokud se shoduje domΘna a ·vodnφ Φßst cesty ke skriptu, kter² cookie odeslal prohlφ₧eΦi. Pokud chceme rozÜφ°it platnost cookie na cel² server, pou₧ijeme jako parametr cesta lomφtko '
/
'. Pomocφ parametru domΘna m∙₧eme rozÜφ°it
platnost cookie na celou domΘnu. Pokud jako hodnotu uvedeme
nap°. 'firma.cz
', bude cookie platnß pro vÜechny
servery v domΘn∞ firma.cz.
Pokud jako hodnotu poslednφho parametru zabezpeΦenφ,
uvedeme true
, bude cookie zaslßna pouze, pokud je mezi
serverem a klientem vytvo°eno bezpeΦnΘ spojenφ pomocφ SSL (Secure Socket
Layer).
Cookies m∙₧eme z prohlφ₧eΦe smazat dv∞ma zp∙soby -- bu∩ jako hodnotu cookie poÜleme prßzdn² °et∞zec nebo platnost cookie nastavφme do minulosti. V obou dvou p°φpadech je nepot°ebnß cookie odstran∞na z prohlφ₧eΦe a nezabφrß zbyteΦnΘ mφsto na disku u₧ivatele.
Pou₧itφ cookies si nynφ ukß₧eme na slo₧it∞jÜφm p°φklad∞. NaÜφm ·kolem bude vytvo°it server, kter² si od ka₧dΘho u₧ivatele p°i vstupu na hlavnφ strßnku vy₧ßdß zodpov∞zenφ jednΘ z otßzek. Otßzka bude pro u₧ivatele vybrßna nßhodn∞, ale zßrove≥ bychom jednomu u₧ivateli nem∞li vφcekrßt poklßdat tutΘ₧ otßzku.
Budeme dßle p°edpoklßdat, ₧e jednotlivΘ otßzky mßme ulo₧eny v
databßzovΘ tabulce Dotaznik
. U ka₧dΘ otßzky mßme ulo₧eno
jejφ identifikaΦnφ Φφslo, zn∞nφ a poΦet hlas∙ pro a proti.
V °eÜenφ naÜeho ·kolu nßm v²born∞ pomohou cookies, proto₧e prßv∞ pomocφ nich si budeme u ka₧dΘho u₧ivatele evidovat, na kterΘ otßzky ji₧ odpov∞d∞l. Z databßze p°i p°ihlßÜenφ k serveru vybereme v₧dy dosud nepoklßdanou otßzku -- to zamezφ zbyteΦnΘmu zkreslenφ v²sledk∙ tφm, ₧e n∞kdo vφcekrßt odpovφ na jednu otßzku.
Proto₧e pro ka₧dΘho u₧ivatele pot°ebujeme evidovat v∞tÜφ poΦet
zodpov∞zen²ch otßzek, vyu₧ijeme toho, ₧e vφce cookies m∙₧e mφt stejnΘ
jmΘno a r∙znou hodnotu -- v PHP s nimi pak pracujeme jako s polem. My si
cookie pojmenujeme zodpovezeneDotazy
. Nßsledujφcφ skript z
tabulky nßhodn∞ vybere jeden dosud nepolo₧en² dotaz a zobrazφ jej:
<HTML> <HEAD> <TITLE>N┴ZORY.CZ</TITLE> </HEAD> <BODY> <? $sql = "select * from Dotaznik"; if (IsSet($zodpovezeneDotazy)) $sql .= " where ID not in (". Implode($zodpovezeneDotazy, ","). ")"; do { MySQL_Connect("localhost"); $vysledek = MySQL("test", $sql); $pocet = MySQL_NumRows($vysledek); if ($pocet==0) break; SRand((double)MicroTime()*1e6); $aktualni = Rand() % $pocet; $id = MySQL_Result($vysledek, $aktualni, "ID"); $dotaz = MySQL_Result($vysledek, $aktualni, "Otazka"); } while (false); if (IsSet($id)): ?> <H1>Pro vstup na server odpov∞zte na nßsledujφcφ otßzku:</H1> <FORM ACTION="17-03.php3"> <?echo $dotaz?><BR><BR> <INPUT TYPE=Submit NAME=Odpoved VALUE="Ano"> <INPUT TYPE=Submit NAME=Odpoved VALUE="Ne"> <INPUT TYPE=Hidden NAME=id VALUE="<?echo $id?>"> </FORM> <?else:?> <H1>Dnes to bude bez otßzky</H1> <A HREF="17-03.php3">Vstupte na nßÜ server</A> <?endif?> </BODY> </HTML>Pochopenφ skriptu nechßm na laskavΘm Φtenß°i, zmφnφm se jen o pßr funkcφch PHP, se kter²mi jsme se dosud nesetkali. Funkce
IsSet()
zjiÜ¥uje, zda danß prom∞nnß obsahuje n∞jakou
hodnotu. Funkce Implode()
vezme jednotlivΘ prvky pole a
navzßjem je spojφ do jednoho °et∞zce -- k odd∞lenφ prvk∙ pole v °et∞zci
se pou₧φvß znak p°edan² jako druh² parametr. Volßnφm
Implode($zodpovezeneDotazy, ",")
tedy zφskßme seznam
identifikaΦnφch Φφsel ji₧ zodpov∞zen²ch dotaz∙, kter² s v²hodou
pou₧ijeme p°i zadßvßnφ SQL-dotazu, kter² vybφrß pouze dosud nepolo₧enΘ
otßzky.
P°φkaz SRand((double)MicroTime()*1e6)
zinicializuje
generßtor nßhodn²ch Φφsel. Funkce Rand()
vracφ nßhodnΘ
Φφslo. Pou₧itφm operßtoru modulo (zbytek po d∞lenφ) upravφme nßhodnΘ
Φφslo na pot°ebn² rozsah.
Nynφ nadeÜel prav² Φas pro skript, kter² zpracuje odpov∞∩ u₧ivatele.
Skript 17-03.php3
mß na starosti mnoho v∞cφ -- p°edn∞ musφ
klientovi odeslat cookie, kterß obsahuje Φφslo zodpov∞zenΘ otßzky. PotΘ
musφ v databßzi aktualizovat poΦet odpov∞dφ pro/proti u danΘ otßzky.
Nakonec skript vypφÜe p°ehled odpov∞dφ na vÜechny otßzky, abychom m∞li
p°ehled.
<? if(IsSet($id)) SetCookie("zodpovezeneDotazy[$id]", $id, Time()+2592000); ?> <HTML> <HEAD> <TITLE>N┴ZORY.CZ</TITLE> </HEAD> <BODY> <H1>V²sledky hlasovßnφ pro vÜechny dotazy</H1> <TABLE CELLSPACING=0 BGCOLOR=BLACK> <TR BGCOLOR=YELLOW><TH>Otßzka<TH WIDTH=120>Ano<TH WIDTH=120>Ne</TR> <? MySQL_Connect("localhost"); $sql = "update Dotaznik"; if ($Odpoved=="Ano") $sql .= " set Ano = Ano + 1"; else $sql .= " set Ne = Ne + 1"; $sql .= " where ID = $id"; $vysledek = MySQL("test", $sql); if (!$vysledek) echo "Nepoda°ilo se zapsat vaÜi odpov∞∩."; $sql = "select * from Dotaznik order by Otazka"; $vysledek = MySQL("test", $sql); $pocet = MySQL_NumRows($vysledek); define("SirkaGrafu", 100); for ($i=0; $i<$pocet; $i++): $ano = MySQL_Result($vysledek, $i, "Ano"); $ne = MySQL_Result($vysledek, $i, "Ne"); echo "<TR><TD COLSPAN=3></TR>". "<TR VALIGN=TOP BGCOLOR='#FFFF80'><TD>". MySQL_Result($vysledek, $i, "Otazka"). "<TD ALIGN=RIGHT>$ano ". ($ano ? "<IMG SRC=bluedot.gif WIDTH=". Round(SirkaGrafu/($ano+$ne)*$ano). " HEIGHT=10>" : ""). "<TD ALIGN=LEFT>". ($ne ? "<IMG SRC=reddot.gif WIDTH=". Round(SirkaGrafu/($ano+$ne)*$ne). " HEIGHT=10>" : "")." $ne". "</TR>"; endfor; ?> </TABLE> </BODY> </HTML>U odesφlanΘ cookie jsme nastavili platnost na 30 dnφ -- nep°edpoklßdßme, ₧e jeden dotaz bude na serveru delÜφ dobu a je zbyteΦnΘ, aby byl prohlφ₧eΦ u₧ivatele zavalen nepot°ebn²mi cookies. V hranat²ch zßvorkßch za nßzvem cookie uvßdφme jedineΦn² index -- PHP nßm nßsledn∞ umo₧nφ s cookie pracovat jako s polem (to vyu₧φvßme v prvnφm skriptu).
P°i psanφ aplikacφ nesmφme vÜak na cookies spolΘhat. U v∞tÜiny prohlφ₧eΦ∙ lze podporu cookies vypnout a n∞kte°φ u₧ivatelΘ d∞lajφ, proto₧e se zcela neoprßvn∞n∞ bojφ ·niku osobnφch informacφ. Profesionßlnφ aplikace by si m∞la poradit i s touto situacφ a pracovat sprßvn∞ -- t°eba jen s omezen²m u₧ivatelsk²m komfortem.
Zßkusek mßme ·sp∞Ün∞ za sebou. KonΦφ i serißl Aplikace na Webu, se kter²m jste na strßnkßch Computerworldu setkßvali vφce ne₧ p∙l roku. Doufßm, ₧e zφskanΘ poznatky vßm byly k u₧itku a ₧e se brzy spoleΦn∞ setkßme u dalÜφch Φlßnk∙ v∞novan²ch webov²m technologiφm. NeΦekejte vÜak s rukama slo₧en²ma v klφn∞ a napiÜte nßm, se kter²mi tΘmaty a technologiemi byste se nejrad∞ji seznßmili.