Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

9. diel - Vylepšenia kontaktného formulára v PHP

V minulej lekcii, Kvíz - Textové reťazce, polia a podmienky v PHP , sme naprogramovali jednoduchý emailový formulár. V dnešnom PHP tutoriálu ho vylepšíme.

Predvyplnenie polí

Keď niečo zle vyplníme, skript nám to oznámia, ale formulár je už prázdny. Je to samozrejme preto, že zobrazujeme už inú stránku, než do ktorej sme dáta zadávali.

Pretože spracovávame dáta tým samým skriptom, v ktorom je formulár, môžeme do formulára jednoducho vložiť hodnoty z POST v prípade, že boli nejaké odoslané. Budete to vyzerať, ako by sa formulár ani nevymazal.

V PHP bloku tesne pred formulárom si naplníme premennej $jmeno, $email a $zprava hodnotami z $_POST. To môžeme urobiť samozrejme len v prípade, keď v POST tieto hodnoty sú. Ak nie, dáme do premenných prázdnej reťazca.

V tejto chvíli by sme kód napísali asi takto:

if (isset($_POST['jmeno']))
    $jmeno = $_POST['jmeno'];
else
    $jmeno = '';

Kód je pomerne dlhý a písať ho pre všetky 3 premenné by bolo nepohodlné. Zvlášť, keď by formulár obsahoval ešte ďalšie pole. Preto si uvedieme tzv. Ternárne výraz. Jedná sa o skrátenú podobu if... else. Ternana výraz vždy vracia nejakú hodnotu, nedá sa teda použiť len miesto podmienky. Skladá sa z troch časti, čo by nás podľa jeho názvu nemalo prekvapiť :) V prvej časti uvedieme podmienku, ďalej znak ? a potom hodnotu, ktorú má výraz vrátiť, ak podmienka platí. Za ňou uvedieme : a hodnotu, ktorá sa má vrátiť, keď podmienka neplatí.

Premennú by sme pomocou ternárního výrazu naplnili takto:

$jmeno = (isset($_POST['jmeno'])) ? $_POST['jmeno'] : '';

Ešte malá rekapitulácia. Ak v POST existuje daný kľúč, vložíme túto hodnotu do premennej $jmeno. Ak nie, vložíme tam prázdny textový reťazec, čo sú jednoducho úvodzovky, medzi ktorými nič nie je.

Toto urobíme ešte s emailom a správou.

Formulár ďalej upravíme tak, aby sa do jeho polí vkladali hodnoty z týchto premenných. Ak nebol formulár odoslaný, vloží sa tam prázdne reťazca, inak sa tam vloží to, čo používateľ vyplnil.

Do formulárového poľa by sme mohli hodnotu vložiť nasledovne:

<input name="jmeno" type="text" value="<?php echo $jmeno ?>" />

Ak chceme v PHP sekvencii len vypísať obsah premennej, použijeme k tomu skrátenú direktívu <?=. Rovnakého výstupu teda môžeme dosiahnuť aj kratšom zápisom:

<input name="jmeno" type="text" value="<?= $jmeno ?>" />

Stále to však nie je ono. Keďže text v premennej $jmeno pochádza od užívateľa, nemôžeme si byť istí, že je bezpečný. Čo keby nám do textu užívateľ vložil nejaký HTML kód? Vložil by sa potom normálne do našej stránky.

V našom prípade by to toľko nevadilo, ale sú prípady, kde áno. Predstavte si, že vypisujú na stránke správy od užívateľov, treba komentáre k nejakému článku. A jeden používateľ namiesto textu správy vložil HTML kód s formulárom, ktorý je nasmerovaný na jeho obslužný skript na inom webe a v ktorom požaduje od vašich používateľov heslo. Pri vypisovaní správy sa tento kód vypíše do stránky a zobrazí sa jeho formulár. Niektorí vaši používatelia tam naozaj zadajú svoje heslo, ktoré sa odošle niekam útočníkovi. A vy máte problém.

Tomuto typu útoku sa hovorí XSS (ako Cross Site Scripting). Obrana je veľmi jednoduchá, pred vypísaním obsahu ktorejkoľvek premenné do HTML kódu stránky použite funkciu htmlspecialchars(). Tá prevedie špicaté HTML zátvorky a pár ďalších znakov na tzv. HTML entity. Prípadný škodlivý kód je potom braný len ako obyčajný text a prehliadač ho nespracuje ako HTML kód.

Je potrebné pri výpise ošetrovať naozaj každú premennú, aj tie, ktoré užívateľ priamo nezadá. Nikdy totiž neviete, či sa obsah premennej neskladá z niečoho, čo užívateľ zadal a jednoducho sa to nedá ustrážiť. Preto sa ošetrí všetko a to priamo na tom mieste, kde premennú vypisujeme. Až budete pokročilejšie a budete poznať objektovú architektúru, dokážete tento proces zautomatizovať, aby ste funkciu nemuseli ručne písať.

Ukážme si konečne upravený HTML kód formulára is direktívou nad ním:

<?php
    if ($hlaska)
        echo('<p>' . htmlspecialchars($hlaska) . '</p>');

    $jmeno = (isset($_POST['jmeno'])) ? $_POST['jmeno'] : '';
    $email = (isset($_POST['email'])) ? $_POST['email'] : '';
    $zprava = (isset($_POST['zprava'])) ? $_POST['zprava'] : '';
?>

<form method="POST">
    <table>
        <tr>
            <td>Vaše meno</td>
            <td><input name="jmeno" type="text" value="<?= htmlspecialchars($jmeno) ?>"/></td>
        </tr>
        <tr>
            <td>Váš email</td>
            <td><input name="email" type="email" value="<?= htmlspecialchars($email) ?>"/></td>
        </tr>
        <tr>
            <td>Aktuálny rok</td>
            <td><input name="rok" type="number" /></td>
        </tr>
    </table>
    <textarea name="zprava"><?= htmlspecialchars($zprava) ?></textarea>
    <br />

    <input type="submit" value="Odoslať" />
</form>

Formulár si vyskúšajme. Ponechajme nejaké pole prázdne a odošleme, ukáže sa chybová hláška a zároveň zostane aj to, čo používateľ vyplnil:

Kontaktný formulár
localhost/mail­form.php

Presmerovanie

Formulár má teraz dve podstatné vady. Ak správu úspešne odošleme, rovnako zostane predvyplnený. A hlavne ak po odoslaní stlačíme F5, formulár sa odošle znova. Týmto neduhom trpí všetky formuláre, ak ho spracováva ten istý súbor, v ktorom je formulár vložený (čo je väčšinou nutné).

Ak je spracovanie formulára dokončené, mali by sme vykonať presmerovanie. Presmerujeme na tú istú adresu, na ktorej je formulár. Vďaka presmerovanie sa však stratí dáta v $_POST. Následné obnovenie stránky tak už nič neodošle.

Presmerovanie vykonáme pomocou funkcie header(). Tá odošle tzv. Hlavičku prehliadači. Práve hlavička môže obsahovať informáciu o presmerovanie a to pomocou slova Location.

Po uložení úspešnej hlášky teda formulár presmerujeme:

if ($uspech)
{
    $hlaska = 'Email bol úspešne odoslaný, čoskoro vám odpovieme.';
    header('Location: mailform.php');
    exit;
}

Funkciou exit() ukončíme beh skriptu, pretože samotné presmerovanie ho nezastaví, len pošle prehliadači návštevníka informáciu o tom, že sa má presunúť na inú lokáciu.

Formulár už netrpí opätovným odoslaním pri obnovení stránky. Nezobrazuje však ani hlášku o úspechu. Malo by vám byť jasné prečo, keď presmerujeme na inú stránku, obsah premenných na stránke existujúce sa stratí a tým aj ten v $hlaska. Riešenie je niekoľko, tým najjednoduchším je odovzdať pomocou GET parametra stránke nejakú premennú. Podľa toho stránka spozná, že na nej bolo presmerované po úspešnom odoslaní a zobrazí o tom správu. Kód zmeníme na nasledujúce podobu:

header('Location: mailform.php?uspech=ano');
exit;

Presunieme sa na začiatok skriptu, kde hlášku nastavujeme na prázdny string. Pozrieme sa, či nám neprišiel v adrese parameter uspech. Ak áno, nastavíme hlášku na text, ktorý sa má pri úspechu užívateľovi vypísať. Už vieme, že parametre z URL adresy prichádzajú na rozdiel od parametrov z formulára v poli $_GET:

$hlaska = '';
if (isset($_GET['uspech']))
    $hlaska = 'Email bol úspešne odoslaný, čoskoro vám odpovieme.';

Môžete si vychutnať dobre fungujúce formulár.

POZOR! Presmerovať môžeme iba v prípade, že sme ešte nevyzvali na predloženie žiadne HTML. Akonáhle sa totiž začne niečo vypisovať, PHP prehliadači odošle hlavičku, kde mu hovorí, že mu posiela HTML súbor. Hlavičku možno samozrejme odoslať len raz, keď sa pokúsime veprostřed súboru presmerovať, dostaneme chybovú hlášku "Headers already sent" a k presmerovanie nedôjde. To by sa stalo napríklad v tomto prípade:

<html>
    <body>
        <?php
            // Tento kód je zle
            header('Location: index.php');
            exit;
        ?>
    </body>
</html>

Dávajte si pozor aj na tento prípad, v ktorom chyba nie je na prvý pohľad vidieť:

-- Tu je prázdna riadok --
<?php

    header('Location: index.php');

?>
<html>
    <body>
    </body>
</html>

Na začiatku súboru je odriadkovanie. Aj to je znak, ktorý odštartuje výstup a PHP ho odosiela prehliadači spolu s hlavičkou. Podobný problém býva s medzerou. Ak ukladáte UTF-8 súbory s tzv. BOM, môže robiť práve tieto problémy. Ak však používate kvalitnú IDE, tak sa vám to nestane.

Pozn .: Niektorí začiatočníci presmerúvajú tak, že vyechují JavaScript, pomocou ktorého zmení adresu okna. Vyzerá asi takto:

// Tento kód je zle
echo('<script type="text/javascript">
    window.location = "index.php"
</script>');

Tento spôsob je však nespoľahlivý a niekedy aj nebezpečný. Nepoužívajte ho.

Formulár si môžete nastylovať, aby vyzeral lepšie. Hlášku dať do nejakej bubliny a podobne. To ale už nie je predmetom tohto PHP kurzu, štýlovanie sa preberá v inom on-line kurzu :) Kompletný formulár je k stiahnutiu nižšie. V budúcej lekcii, Skladanie stránok v PHP , sa pozrieme na skladanie stránok pomocou PHP.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 4441x (3.13 kB)
Aplikácia je vrátane zdrojových kódov v jazyku php

 

Predchádzajúci článok
Kvíz - Textové reťazce, polia a podmienky v PHP
Všetky články v sekcii
Základné konštrukcie jazyka PHP
Preskočiť článok
(neodporúčame)
Skladanie stránok v PHP
Článok pre vás napísal David Hartinger
Avatar
Užívateľské hodnotenie:
1 hlasov
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David sa informačné technológie naučil na Unicorn University - prestížnej súkromnej vysokej škole IT a ekonómie.
Aktivity