Předávání dat mezi formuláři

Často nám uživatel na formuláři sdělí údaje, se kterými potřebujeme pracovat i později, ale nechceme se jej na to pořád dokola ptát. Zde si ukážeme několik způsobů, jak tento problém řešit.

Input pole typu hidden

Nejčastější je problém, kdy pro zásah do dat i předtím k jejich zobrazení se má zadávat jméno a heslo. Správné řešení je vyžadovat přihlášení prostřednictvím souboru .htaccess, vedoucímu k použití protokolu https, ale to vyžaduje přihlášení uživatelským jménem na serveru. Pokud nejsme současně správci serveru, je toto řešení nedostupné. Alternativně může stránka opakovaně předávat svým následovníkům data jako položku formuláře typu hidden. Podotýkám, že protože se jedná o nezabezpečený (a tedy většinou i nezakódovaný) přenos, může být napaden hackerem.

Postup ukazují tři formuláře: první zažádá o jméno a heslo, další o nějaká další data, třetí vypíše údaje z obou. Úlohu druhého formuláře by šlo několikrát zopakovat, pro vyzkoušení principu to ale není třeba.

První stránka s formulářem je normální html stránka. Můžete si ji vyzkoušet na adrese tem.wz.cz/form1.htm:

<html>

<head>
<meta http-equiv="Content-Type"
content="text/html; charset=windows-1250">
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
<title>Předávání dat mezi formuláři...</title>
</head>

<body bgcolor="#FFFFFF">

<p><font size="4"><strong>Prosíme, přihlaste se dle nápovědy:</strong></font></p>

<form action="form2.php" method="post">
    <p>Zadejte jméno : <input type="text" size="20"
    name="jmeno1"> scott<br>
    Zadejte heslo: <input type="text" size="20" name="hodnota1">
    tiger<br>
    <input type="submit" name="odeslat" value="Odeslat"></p>
</form>

<p><sub>poslední verze 31.3.2010</sub> </p>
</body>
</html>

Druhá stránka dynamicky generuje formulář na základě dat a vloží do něj již získaná data jako položku hidden (znázorněno tučně):

</head>

<body bgcolor="#FFFFFF">

<?php
if (($odeslat=="Odeslat")and($jmeno1=="scott")and($hodnota1=="tiger")):
?>

<p><font size="4"><strong>Můžete vyplnit další dva údaje:</strong></font></p>

<form action="form3.php" method="post">
    <p>Zadejte prvni slovo : <input type="text" size="20" name="jmeno2"><br>
    Zadejte druhe slovo: <input type="text" size="20" name="hodnota2">
    <br>


<?php
echo '<input type="hidden" name="jmeno" value="'.$jmeno1.'">';
echo '<input type="hidden" name="heslo" value="'.$hodnota1.'">';
?>
    <input type="submit" name="odeslat" value="Odeslat"></p>
</form>
<?php
else: 
?>
Přihlášení se nepovedlo. <a href="form1.htm">Zkuste znovu</a>.
<?php
endif; 
?>
<p><sub>poslední verze 31.3.2010</sub> </p>
</body>
</html>

Vzhledem k tomu, že se výstup php skriptu musel generovat včetně uvozovek, bylo nutno použít apostrofy, které ale v php (na rozdíl od javascriptu) mají jiný význam, a pro sloučení s hodnotou proměnné bylo proto nutno použít tečku, která má význam spojení dvou (zde postupně tří) řetězců.
Poznámka: Zadaná hodnota nesmí obsahovat například uvozovky nebo obrácené lomítko. Nutno ošetřit.

Třetí formulář jen přebírá a zobrazuje všechna data. Postup jsme již probírali:

<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1250">
<title>Předávání dat mezi formuláři...</title>
</head>

<body bgcolor="#FFFFFF">

<p><font size="4"><strong>Bylo zadáno:</strong></font></p>

<table border=1>
<?php
foreach($_POST as $jm => $hodn) {echo "<tr><td>".$jm."<td>".$hodn; };
?>
</table>

<p><sub>poslední verze 31.3.2010</sub> </p>
</body>
</html>

Formuláře používají metodu post, takže uživatele předávaná data zbytečně neobtěžují. Ale pokud si zobrazí zdrojový kód, pak je samozřejmě všechna vidí. Tyto skripty si můžete vyzkoušet na adrese tem.wz.cz/form1.htm uvedené výše - na druhý a třetí je třeba projít vyplněním formulářů. Podotýkám, že ověření podpisu na druhém formuláři takto nefunguje.

Cookies

Obvyklejší formou dočasného ukládání dat jsou cookies. Jedná se o ukládání proměnných na straně klienta (tam, kde běží program, který stránku zobrazuje). Proměnná je pak typicky k dispozici všem php skriptům ve stejném adresáři, a objeví se bez potřeby dalšího zásahu v asociativním poli $_COOKIE (na serveru webzdarma je stále aktivní "register global", takže i jako proměnná). Funkce pro vytvoření nové cookie proměnné má tvar:

setcookie(jméno,hodnota,doba_expirace,adresář_platnosti,doména_platnosti);

Častěji se používá jen s prvními dvěma parametry (jméno a hodnota), ale pak zmizí po uzavření okna prohlížeče. Pokud zadáme dobu expirace, pak zmizí až po této expiraci. Například v manuálu doporučují posunout aktuální čas o měsíc následujícím výpočtem:

time()+60*60*24*30 

Čas se v Unixu udává ve vteřinách, uplynulých od 1.1.1970 (o deset let starší, než operační systémy Microsoft). Podobným způsobem je možné zajistit, že "stránka" si pro každého uživatele pamatuje jeho nastavení. My potřebujeme uchovávat data jen do uzavření okna formuláře, takže jsem navrhl následující pokusný skript:

<html>

<head>
<meta http-equiv="Content-Type"
content="text/html; charset=windows-1250">
<title>Cookie...</title>

</head>

<body bgcolor="#FFFFFF">

<?php
if ($zadat=='Zadat') setcookie($jmeno1,$hodnota1,0) ;
?>

<p><font size="4"><strong>Aktuální stav Cookies:</strong></font></p>

<table border=1>
<?php
foreach($_COOKIE as $jmeno => $hodnota) {echo "<td>".$jmeno."<td>".$hodnota; };
?>
</table>

<p><font size="4"><strong>Zadejte novou Cookie:</strong></font></p>

<form action="cookie1.php" method="get">
Zadejte jmeno nove cookie: <input name="jmeno1" type="text">  
<br>  
Zadejte hodnotu nove cookie: <input name="hodnota1" type="text">  
<br>  
<input name="zadat" value="Zadat" type="submit"></form>  
<p>&nbsp;</p>
<sub>poslední verze 25.3.2010</sub>
</body>
</html>

Volá opakovaně sám sebe. Vždy nejprve vypíše celé asociativní pole $_COOKIE a pak umožní zadat další jméno a hodnotu proměnné typu cookie. Zbývá podotknout, že dle doporučení manuálu jsem čas (třetí parametr) nevynechal, ale dosadil zde nulu. Tento skript si můžete vyzkoušet zde.

Session

Cookie ovšem mívají uživatelé vypnuté. Samozřejmě je možné si proměnné ukládat i na server. K tomu slouží session. Systém session je třeba vždy nejprve inicializovat:

session_start();

Pak je k dispozici asociativní pole $_SESSION , obsahující jednotlivé proměnné. Například novou proměnnou "barva" o hodnotě "žlutá" přidáme příkazem:

$_SESSION["barva"] = "žlutá";

Hodnotu proměnné barva zobrazíme například příkazem:

echo $_SESSION["barva"];

Nedostatkem je, že jsme se problému se zakázanými cookie vůbec nezbavili. Pro inicializaci asociativního pole je totiž třeba zadat jakousi klíčovou inicializační proměnnou, která nám zpřístupní naši sadu session - pokud neřekneme jinak, zapíše nám ji systém opět do cookie. Systém se přitom nějak inicializovat musí, protože pole session může používat více stránek (které si asi nemají vzájemně měnit data), nebo třeba jen je z principu serveru možné, že více uživatelů pracuje současně s toutéž stránkou. Abychom se zbavili závislosti na klientovi, můžeme session inicialitovat vhodným jménem:

session_name('alik');
session_start();

Tento obrat můsí být na každé stránce, kde se mají session použít. Zbývá otázka, jak se projeví, když na téže stránce začne pracovat (=používat ji) více uživatelů. Alternativně by bylo možné si název session náhodně vygenerovat a předávat z formuláře na formulář, jako v prvním příkladě. Pokud předáváme z formuláře na formulář přihlašovací jméno a heslo uživatele, můžeme pro funkci session_name samozřejmě použít právě toto přihlašovací jméno. Uživatel pak bude mít dokonce stejné nastavení k dispozici při příštím přihlášení.

Řešení, obdobné ukázce s cookie, by pak vypadalo následovně:

<html>

<head>
<meta http-equiv="Content-Type"
content="text/html; charset=windows-1250">
<title>Session</title>

</head>

<body bgcolor="#FFFFFF">

<?php
session_name('alik');
session_start();

if ($zadat=='Zadat') $_SESSION[$jmeno1] = $hodnota1;

?>

<p><font size="4"><strong>Aktuální stav systému proměnných session:</strong></font></p>

<table border=1>
<?php
foreach($_SESSION as $jmeno => $hodnota) {echo "<tr><td>".$jmeno."<td>".$hodnota; };
?>
</table>

<p><font size="4"><strong>Zadejte novou proměnnou:</strong></font></p>

<form action="cookie2.php" method="get">
Zadejte jméno nové proměnné: <input name="jmeno1" type="text">  
<br>  
Zadejte hodnotu nové proměnné: <input name="hodnota1" type="text">  
<br>  
<input name="zadat" value="Zadat" type="submit"></form>  
<p>&nbsp;</p>
<sub>poslední verze 31.3.2010</sub>
</body>
</html>

Stránka opět opakovaně volá sama sebe. Mně osobně z neznámých důvodů obrat "foreach" z asociativního pole nejprve vytáhne proměnnou beze jména a bez hodnoty. Na běžné použití session to ovšem nemůže mít vliv. Tento skript si můžete vyzkoušet zde.

Porovnání

Session si můžete odladit sami a nejste závislí na funkčnosti prohlížeče na straně klienta. Cookie se zase dobře hodí pro uložení lokálního nastavení stránky - výhodou je, že uživatel to čeká a může si všechny cookies sám kdykoli smazat. Obvyklá obsluha cookies by asi představovala načtení všech uložených třeba s životností 30 dní a jejich opětovné zapsání se stejnou životností, ale od současného okamžiku zpět (občerstvení). Cookie, dostupné po dobu, než se opustí adresář na serveru (např. zavřením okna prohlížeče), se snadno vytvoří zadáním nuly místo životnosti proměnné - to je umožněno tím, že změnu adresáře či serveru vyhodnocuje prohlížeč na straně klienta, který ví, že se tak stalo, a může vše "uklidit".