Získej svůj iPhone v nové soutěži! Získej svůj iPhone v nové soutěži!
Nová překladatelská soutěž ITnetwork.cz o telefon iPhone, sluchátka Beats a další věcné ceny za 4 hodiny práce.
Přidej si svou IT školu do profilu a najdi spolužáky zde na síti :)

8. díl - Kontaktní emailový formulář v PHP

PHP Základní konstrukce Kontaktní emailový formulář v PHP American English version English version

ONEbit hosting Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Podmínky v PHP podruhé - přetypování, skládání a switch, jsme dokončili podmínky. Na dnešní PHP tutoriál máme slíbený kontaktní formulář, do kterého návštěvníci našich stránek napíší vzkaz a ten se nám odešle emailem. Jedná se o velmi užitečný webový doplněk, díky kterému nás mohou uživatelé našich stránek lépe kontaktovat.

HTML část

Jako vždy bude aplikace rozdělena na 2 části. V tomto případě ovšem budou obě v jednom souboru mailform.php. Je to z toho důvodu, abychom měli při zpracování dat z formuláře přístupný i formulář. Pokud uživatel zadá něco špatně, vypíšeme nad formulář chybovou hlášku.

HTML část bude tedy obsahovat formulář, který bude mít následující prvky:

  • Jméno - Jméno návštěvníka (abychom věděli kdo nám píše)
  • Emailová adresa - Emailová adresa návštěvníka (abychom mu mohli odpovědět)
  • Zpráva - Zpráva od uživatele
  • Antispam - Ochrana proti spamu

Kromě ochrany proti spamu asi není co vysvětlovat. Řekněme si tedy o spamu více.

Spam

Jakmile vložíte na internet nějakou stránku s formulářem, objeví se časem roboti, kteří do formuláře začnou psát reklamu. Důvod je prostý, formulář někam něco odesílá a když do něj vloží odkaz na nějaké služby (často půjčky nebo pornografii), část lidí na tu reklamu klikne a služby si koupí.

Proti spamu se dá velmi účinně bránit. K zabezpečení formulářů se používá tzv. Turingův test, známý spíše pod pojmem Captcha. Účelem testu je položit takovou otázku, na kterou zná odpověď jen člověk. První captchy často zobrazovaly text na obrázku a předpokládalo se, že obrázek umí přečíst jen člověk. Postupem času však spameři vyvinuli poměrně sofistikované OCR čtečky, které umí obrázky číst lépe, než lidé. Není ovšem nic jednoduššího, než položit nějakou otázku (nejlépe česky), kterou spamboti neumějí. Bohatě nám bude stačit např. "Zadejte aktuální rok".

Formulář

Založte si tedy nový projekt a můžeme začít. HTML kód stránky s formulářem by mohl vypadat např. takto:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Kontaktní formulář</title>
    </head>
    <body>
        <p>Můžete mě kontaktovat pomocí formuláře níže.</p>

        <form method="POST">
            <table>
                <tr>
                        <td>Vaše jméno</td>
                        <td><input name="jmeno" type="text" /></td>
                </tr>
                <tr>
                        <td>Váš email</td>
                        <td><input name="email" type="email" /></td>
                </tr>
                                <tr>
                        <td>Aktuální rok</td>
                        <td><input name="rok" type="number" /></td>
                </tr>
                </table>
                <textarea name="zprava"></textarea><br />

            <input type="submit" value="Odeslat" />
        </form>

    </body>
</html>

A výsledek:

Kontaktní formulář
localhost/mail­form.php

Formulář jsme vložili do tabulky, aby byly prvky hezky zarovnané. Dělá se to tak často, pokud chceme formulář rychle nastylovat. Všimněte si, že ve formuláři není vyplněný parametr action. Data se tedy odešlou na ten samý soubor, ve kterém je formulář.

PHP část

Na úplný začátek souboru vložíme PHP direktivu a pustíme se do programování:

<?php

?>

Validace

Každý formulář bychom měli zvalidovat. Validace je ověření, zda je správně vyplněný. Sice ještě neumíme ověřit, zda jsou v polích správné hodnoty, ale umíme zjistit, zda nejsou prázdná.

Kromě toho, že pole přišlo prázdné, je ještě jedna možnost - formulář se nemusel vůbec odeslat. S touto možností musíme počítat, jelikož máme zpracování i zobrazení ve stejném skriptu - uživatel mohl zatím jen zobrazit formulář a nic neodeslat. Z minulé lekce víme, že pokud napíšeme:

if ($_POST)

Provede se podmínka v případě, když pole není prázdné.

Dále bychom měli počítat i s tím, že se formulář neodeslal celý, ale jen jeho část. Potřebujeme tedy zjistit, zda v $_POST existují jednotlivé proměnné. K tomu v PHP slouží funkce isset().

POZOR! Mnoho začátečníků používá k ověření toho, zda se něco odeslalo, následující kód:

if ($_POST['jmeno'])
{
        // ...
}

To je ovšem špatně a pokud se formulář neodeslal, PHP vypíše ošklivou chybu, jelikož čteme z neexistující proměnné. Tito začátečníci si místo toho, aby kód opravili, vypnou výpis chyb v PHP. Později sem chodí a diví se, že jim něco nefunguje a nemohou chyby najít.

Když už jsme u nastavení chyb, tak musí být vždy takové, že jsou na lokálním serveru (na vašem počítači při testování) zapnuté a na produkci (na internetu) vždy vypnuté. Jen tak odhalíte při testování většinu problémů a na produkci vám nikdo díky viditelné chybové hlášce nebude napadat aplikaci. Chyby lze zapínat a vypínat v php.ini, někdy ovšem na produkci nemusíme mít k tomuto nastavení přístup a existuje k tomu nějaký přepínač v administrátorském rozhraní daného webhostingu.

Validace formuláře by mohla vypadat asi takto:

$hlaska = '';
if ($_POST) // V poli _POST něco je, odeslal se formulář
{
        if (isset($_POST['jmeno']) && $_POST['jmeno'] &&
                isset($_POST['email']) && $_POST['email'] &&
                isset($_POST['zprava']) && $_POST['zprava'] &&
                isset($_POST['rok']) && $_POST['rok'] == date('Y'))
        {
                // Sem přijde odeslání emailu
        }
        else
                $hlaska = 'Formulář není správně vyplněný!';
}

Celý kód je v podmínce, která kontroluje, zda je něco v poli $_POST. Pokud se nic neodeslalo, není co zpracovávat. Další složená podmínka kontroluje, zda byla odeslána jednotlivá pole a zda v nich je nějaký text. U roku samozřejmě kontrolujeme, zda je aktuální. Ve skriptu používáme proměnnou $hlaska, kam vložíme hlášku pro uživatele v případě, že se validace nepovedla. Tu později vypíšeme v HTML části skriptu.

Zpracování

Samotné odeslání emailu není složité. Slouží k tomu funkce mb_send_mail(), která narozdíl od starší funkce mail() podporuje UTF-8 kódování. K funkcím s prefixem mb_ se ještě dostaneme, nyní nám musí stačit, že pokud je chceme používat, často musíme na úplném začátku souboru nastavit kódování:

<?php
mb_internal_encoding("UTF-8");

Přejděme dovnitř naší podmínky s validací a umístěme tam odeslání emailu a nastavení zprávy pro uživatele:

$hlavicka = 'From:' . $_POST['email'];
$hlavicka .= "\nMIME-Version: 1.0\n";
$hlavicka .= "Content-Type: text/html; charset=\"utf-8\"\n";
$adresa = '[email protected]';
$predmet = 'Nová zpráva z mailformu';
$uspech = mb_send_mail($adresa, $predmet, $_POST['zprava'], $hlavicka);
if ($uspech)
{
        $hlaska = 'Email byl úspěšně odeslán, brzy vám odpovíme.';
}
else
        $hlaska = 'Email se nepodařilo odeslat. Zkontrolujte adresu.';

Do několika proměnných si připravíme hlavičku, adresu, kam se má email odeslat (tu si samozřejmě nastavte na svou) a předmět. Jak vypadá hlavička je dané a nemusíte nad tím přemýšlet, podstatná je jen proměnná v prvním řádku, která určuje odesílatele emailu. Email potom vypadá jako že přišel z této adresy, i když ho odeslalo PHP z vašich stránek. Funkce mb_send_mail() vrací true pokud se odeslání podařilo a false pokud selhalo. Tuto hodnotu si uložíme do proměnné $uspech a nastavíme podle ní hlášku.

Úprava formuláře

Vraťme se k našemu formuláři a vložme těsně nad tag form další PHP sekvenci, ve které vypíšeme proměnnou $hlaska, pokud v ní něco je:

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

Hotovo. Váš formulář by měl nyní odesílat emaily a zobrazovat chybové hlášky. Musíte to ale vyzkoušet spíše tak, že si ho nahrajete někam na webhosting. V XAMPPu ve výchozím nastavení není odesílání emailů funkční, i když jde nastavit v konfiguračním souboru. Pokud máte s nastavením problémy, nevadí, prostě si formulář někam nahrajte (třeba na webhosting OneBit) a vyzkoušejte ho online.

Kontaktní formulář
localhost/mail­form.php

V příští lekci, Vylepšení kontaktního formuláře v PHP, formulář dokončíme. Pokud jste měli s nějakou částí problém, níže jsou zdrojové kódy ke stažení.


 

Stáhnout

Staženo 3957x (1.2 kB)
Aplikace je včetně zdrojových kódů v jazyce php

 

 

Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
29 hlasů
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity (6)

 

 

Komentáře
Zobrazit starší komentáře (186)

Avatar
Martin Bubník:21. června 19:17

Ahoj, emaily to odesílá.

 
Odpovědět 21. června 19:17
Avatar
Jana Klečková:10. srpna 18:54

Ahoj,
použila jsem tento ukázkový kód pro zasílání zpráv z webu a asi po hodinovém zkoušení a trápení jsem zjistila, že je funkční na doméně, kde provider poskytuje PHP 5.3.3 ale nefunguje na doméně kde je PHP 5.5.38. Může mi nějaká dobrá duše poradit, jak mám skript změnit, aby fungoval i s PHP 5.5.38? Děkuji moc

 
Odpovědět 10. srpna 18:54
Avatar
Odpovídá na Jana Klečková
Jana Klečková:11. srpna 7:49

problém vyřešen, chaos na straně poskytovale webhostingu...

 
Odpovědět 11. srpna 7:49
Avatar
michal č
Člen
Avatar
michal č:15. srpna 23:23

zdravím,
emaily mi chodí ale když něco zadám ve formuláři do pole jméno tak v přichozím emailu se tam nic nezobrazí nevím kde mám chybu děkuji

<?php

        /*
         *             __          __                __
         *        ____/ /__ _   __/ /_  ____  ____  / /__ _________
         *       / __  / _ \ | / / __ \/ __ \/ __ \/ //_// ___/_  /
         *      / /_/ /  __/ |/ / /_/ / /_/ / /_/ / ,< _/ /__  / /_
         *      \__,_/\___/|___/_.___/\____/\____/_/|_(_)___/ /___/
         *
         *
         *      TUTORIÁLY  <>  DISKUZE  <>  KOMUNITA  <>  SOFTWARE
         *
         *      Tento zdrojový kód je součástí tutoriálů na programátorské
         *      sociální síti WWW.DEVBOOK.CZ
         *
         *      Kód můžete upravovat jak chcete, jen zmiňte odkaz
         *      na www.devbook.cz :-)
         */

    mb_internal_encoding("UTF-8");

    $hlaska = '';
    if ($_POST) // V poli _POST něco je, odeslal se formulář
    {
        if (isset($_POST['jmeno']) && $_POST['jmeno'] &&
                        isset($_POST['email']) && $_POST['email'] &&
                        isset($_POST['zprava']) && $_POST['zprava'] &&
                        isset($_POST['rok']) && $_POST['rok'] == date('Y'))
        {
            $hlavicka = 'From:' . $_POST['email'];
                  //    $hlavicka = 'From:[email protected]';
            $hlavicka .= "\nMIME-Version: 1.0\n";
            $hlavicka .= "Content-Type: text/html; charset=\"utf-8\"\n";
            $adresa = '[email protected]';
            $predmet = 'Přihláška na soutěž 2017';
            $uspech = mb_send_mail($adresa, $predmet, $_POST['zprava'], $hlavicka);
            if ($uspech)
            {
                $hlaska = 'Email byl úspěšně odeslán, brzy vám odpovíme.';
                                 header('Location: http://sdh.cz');
                exit;
            }
            else
                $hlaska = 'Email se nepodařilo odeslat. Zkontrolujte adresu.';
        }
        else
            $hlaska = 'Formulář není správně vyplněný!';
    }

?>

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Kontaktní formulář</title>
    </head>
    <body>
        <p>Přihlašovací formulář pro poharovou soutěž SDH 2017</p>

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

        <form method="POST">
            <table>
                <tr>
                        <td>Název SDH</td>
                        <td><input name="jmeno" type="text" /></td>
                </tr>
                <tr>
                        <td>Váš email</td>
                        <td><input name="email" type="email" /></td>
                </tr>
                                <tr>
                        <td>Aktuální rok(antispam)</td>
                        <td><input name="rok" type="number" /></td>
                </tr>
                <tr>
            <td>Počet družstev</td>
            <td>
            <textarea name="zprava"><?= htmlspecialchars($zprava) ?></textarea>
            </td>

            </table>

            <input type="submit" value="Odeslat" />
        </form>

    </body>
</html>
Editováno 15. srpna 23:25
 
Odpovědět 15. srpna 23:23
Avatar
Odpovídá na michal č
Michal Šmahel:16. srpna 12:53

Ahoj, obsah pole (uložený v $_POST['jmeno']) nikde nepoužíváš. Kde chceš mít jméno vypsané??

Odpovědět 16. srpna 12:53
Nejdůležitější je motivace, ovšem musí být doprovázena činy.
Avatar
EweN
Člen
Avatar
EweN:17. října 14:36

Ahoj, co může způsobovat chybu v tomhle?

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

Mám to vložené přesně podle instrukcí těsně nad form .. ale hlásí mi to chybu na řádku s ECHO.

 
Odpovědět 17. října 14:36
Avatar
EweN
Člen
Avatar
Odpovídá na EweN
EweN:17. října 14:42

Problém vyřešen.. Kdyby někdo řešil to samé .. mrkněte jestli máte soubor uložen jako .php

 
Odpovědět 17. října 14:42
Avatar
Miroslav Mucha:2. listopadu 14:08

Ahoj, při testování kontaktních údajů zadaných do jednotlivých polí jsem zjistil, že formulář se odešle i když např. do pole "jmeno" nebo "zprava" klepnu jenom mezeru. Stejně tak to projde, když se tam zadá například hodnota NULL. Tak jsem to zkusil ošetřit a už to mezery atd. nezpracuje a vyhodí chybu. Chci se zeptat, zda jsem se touto úpravou nedopustil něčeho nekorektního

<?php
if($_POST)  // konrola, zda byl formulář odeslán
{
    if(isset($_POST['jmeno']) && !empty($_POST['jmeno']) && !ctype_space($_POST['jmeno']) &&
       isset($_POST['email']) && !empty($_POST['email']) &&
       isset($_POST['zprava']) && !empty($_POST['zprava']) && !ctype_space($_POST['zprava']) &&
       isset($_POST['rok']) && !empty($_POST['rok'] == date('Y')))
    {
         //Sem přijde odeslání emailu
    }
    else
    {
        $hlaska =  "Formulář není správně vyplněný!";
    }
}

?>
 
Odpovědět 2. listopadu 14:08
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Miroslav Mucha
David Čápka:2. listopadu 15:05

empty() funguje i když tam klíč není, nevyhodí chybu. Nemusíš tam tedy používat isset(), když jsi tam dal empty(). Jinak to vypadá ok. Zvalidovat formulář dobře je samozřejmě dost práce, proto se to řeší až dále v kurzech, konkrétně se na to implementuje framework v kurzu Knihovny pro PHP

Odpovědět 2. listopadu 15:05
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
Odpovídá na David Čápka
Miroslav Mucha:2. listopadu 17:21

Děkuju za odpověď :-)

 
Odpovědět 2. listopadu 17:21
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 196. Zobrazit vše