Python týden Geek tričko zdarma
Tričko zdarma! Stačí před dobitím bodů použít kód TRIKO15. Více informací zde
Pouze tento sleva až 80% na kurzy Python

Lekce 5 - Kontaktní formulář

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, Propojení kontroleru a pohledu, jsme propojili pohled s kontrolerem. Dokonce jsme také přidali již jednu součást webu, kterou je chybová stránka. V dnešním dílu si do webu zkusíme naprogramovat od nuly novou funkčnost po vzoru MVC. Půjde o kontaktní formulář. V principu nás již nic nového nepotká, základ systému máme hotový.

Šablona

Ve složce pohledy si vytvořme kontakt.phtml, kam vložíme jednoduchý HTML kód s formulářem. Formulář bude obsahovat pole pro emailovou adresu návštěvníka (abychom mu mohli odpovědět), dále pole pro antispam (realizujeme jako zadání aktuálního roku), textové pole se zprávou a odesílací tlačítko.

<h1>Kontaktní formulář</h1>

<p>Kontaktujte nás odesláním formuláře níže.</p>

<form method="post" id="form-email">
        Vaše emailová adresa<br />
        <input type="email" name="email" required="required" value="<?php if (isset($_POST['email'])) echo(htmlspecialchars($_POST['email'])); ?>" /><br />
        Antispam - zadejte aktuální rok<br />
        <input type="text" name="rok" required="required" /><br />
        <textarea name="zprava"><?php if (isset($_POST['zprava'])) echo(htmlspecialchars($_POST['zprava'])); ?></textarea><br />
        <input type="submit" value="Odeslat" />
</form>

Kód je jen čisté HTML. Všimněte si využití HTML 5 validátorů. Validovat bychom měli i na straně PHP, ale to nyní opomeneme. Formulář jsme vytvořili opravdu co nejjednodušeji, nepoužili jsme v něm labely a rozložení jsme docílili pouze pomocí <br >. Pokud uživatel již odeslal nějaká data a server je odmítl, měla by aplikace tato data znovu vložit do formuláře, k tomu ty funkce echo(). Pro složitější formuláře by se vyplatilo používat knihovnu, která ho sama vygeneruje a také po odeslání zvaliduje i na serveru, případně sama vyplní. To je ale v současné době nad rámec našich schopností, až budete pokročilejší, můžete se podívat do místní sekce PHP knihovny, kde se taková knihovna vyrábí.

Aby formulář nějak vypadal, přidáme nějaké minimum stylů do našeho styl.css:

input[type="submit"] {
        background: #6FA4F8;
        color: white;
        padding: 5px 10px;
        border-radius: 10px;
        border: 0px;
}

input[type="submit"]:hover {
        background: #2976f8;
        color: #EEEEEE;
        cursor: pointer;
}

input[type="text"], input[type="email"], input[type="password"] {
        width: 250px;
        border-radius: 5px;
        border: 1px solid #aaaaaa;
        padding: 0.3em;
}

input[type="submit"] {
        padding: 10px 25px;
        display: block;
        margin: 0 auto;
        margin-top: 20px;
        font-weight: bold;
}

textarea {
        border-radius: 5px;
        border: 1px solid #aaaaaa;
        width: 483px;
        height: 90px;
}

Model

K odeslání emailu je zapotřebí nějaká logika. Veškerou logiku aplikace budeme psát do modelů. Kontrolery často svádí k jejich přetěžování a začátečníci se do nich snaží psát i logiku, ale nesmíme zapomínat na to, že slouží jen k propojení. Jediné, čím se zatěžují, je zpracování parametrů od uživatele a volání příslušné logiky, která už není jejich součástí.

Vytvoříme si tedy model pro odeslání emailu na určitou adresu. Do složky models si přidejte soubor OdesilacEmailu. Bude v něm následující třída:

class OdesilacEmailu
{

        // Odešle email jako HTML, lze tedy používat základní HTML tagy a nové
        // řádky je třeba psát jako <br /> nebo používat odstavce. Kódování je
        // odladěno pro UTF-8.
        public function odesli($komu, $predmet, $zprava, $od)
        {
                $hlavicka = "From: " . $od;
                $hlavicka .= "\nMIME-Version: 1.0\n";
                $hlavicka .= "Content-Type: text/html; charset=\"utf-8\"\n";
                return mb_send_mail($komu, $predmet, $zprava, $hlavicka);
        }

}

Třída obsahuje pouze jednu metodu odesli(), která bere v parametrech adresu příjemce, předmět, zprávu a adresu odesílatele. Uvnitř sestavíme hlavičku a email odešleme pomocí funkce mb_send_mail(). Ta obaluje obyčejnou PHP funkci mail a dodává jí podporu UTF8 kódování.

Ti bystřejší si všimli, že email se posílá jako HTML. Všechny emaily v našem RS budeme posílat jako HTML, máme tak možnost psát klasický text i text nějak ozdobený. Pouze nesmíme zapomínat, že místo "\n" píšeme <br />.

Kontroler

Nakonec vytvoříme onoho prostředníka, kterým bude KontaktKontroler. Uveďme si rovnou celý jeho kód, který si záhy popíšeme:

<?php

class KontaktKontroler extends Kontroler
{
        public function zpracuj($parametry)
        {
                $this->hlavicka = array(
                        'titulek' => 'Kontaktní formulář',
                        'klicova_slova' => 'kontakt, email, formulář',
                        'popis' => 'Kontaktní formulář našeho webu.'
                );

                if (isset($_POST["email"]))
                {
                        if ($_POST['rok'] == date("Y"))
                        {
                                $odesilacEmailu = new OdesilacEmailu();
                                $odesilacEmailu->odesli("[email protected]", "Email z webu", $_POST['zprava'], $_POST['email']);
                        }
                }

                $this->pohled = 'kontakt';
    }
}

Kontroler dědí z Kontroler a implementuje metodu zpracuj(). V metodě nastavíme nějakou hlavičku a podíváme se, zda přišel formulář. Pokud ano, zkontrolujeme rok. Při úspěchu vytvoříme OdesilacEmailu (model) a předáme mu parametry od uživatele. Samotnou logiku již provede model, kontroler ho pouze volá. Nakonec nastavíme pohled na "kontakt". admin@adresa.cz si samozřejmě nahraďte svým emailem.

Můžeme novou stránku vyzkoušet, přejděme na url kontakt a měli bychom vidět něco takového:

Kontaktní formulář
localhost/kontakt

Princip jak RS ke stránce došel je snad jasný, ale opakování je matka moudrosti. Směrovač podle prvního parametru v URL ("kontakt") zjistí, voláme KontaktKontroler a předá mu řízení aplikace. Pokud jsme formulář již odeslali, KontaktKontroler vytvoří model OdesilacEmailu a předá mu data od uživatele. Model email s daty odešle. Kontroler nakonec vypíše svou šablonu.

Pokud nemáte na localu zprovozněný SMTP server, email vám nedorazí a budete si aplikaci muset vyzkoušet na produkci nebo mi věřit, že je to takhle správně :)

Zprávy

Bylo by opravdu skvělé, kdybychom po odeslání emailu zobrazili uživateli zprávu, že byl odeslán. Nebo naopak, že se to z nějakého důvodu nepovedlo. Pokazit se mohlo samotné odesílání nebo uživatel špatně zadal antispamovou kontrolu. Jistě bychom mohli do šablony vložit nějakou proměnnou s textem zprávy a v EmailKontroler ji nastavovat. Takovou funkčnost ale jistě nebudeme potřebovat jen zde, ale v mnoha dalších kontrolerech a modelech. Proto zobrazování zpráv integrujeme do našeho redakčního systému. O tom pojednává další lekce, Založení databáze a přístupy k ní v PHP.


 

Stáhnout

Staženo 1683x (9.4 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?
17 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 sítě se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Předchozí článek
Propojení kontroleru a pohledu
Všechny články v sekci
Jednoduchý redakční systém v PHP objektově (MVC)
Miniatura
Následující článek
Založení databáze a přístupy k ní v PHP
Aktivity (6)

 

 

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

Avatar
Michal Šmahel:13. května 7:50

Ahoj, jak je vidět, nic jak to z článku nepochopil. Než budeš číst dál, raději si ho přečti ještě jednu.

Data z $_POST se předávají v kontroleru přes metodu volanou na modelu, takže se data do modelu dostanou takto jednoduše. Model o $_POST vůbec neví, odkud mu potřebné parametry došli nepotřebuje vědět.

Jaký kontroler se použije, je dáno v URL (tady "kontakt" -> KontaktKontroler). Kontroler si poté sám určí, jaký model bude potřebovat a zajistí si jeho instanci.

Autoloader načítá soubory s třídami. Dokud soubor nenačteš, PHP třídu "nevidí". Určitě ale neřeší nic víc.

Pokud ve formuláři přímo nezadáš URL, použije se stávající. Požadavek tedy opět přijde na KontaktKontroler.

Odpovědět  +1 13. května 7:50
Nejdůležitější je motivace, ovšem musí být doprovázena činy.
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:13. května 8:46

Ted koukam na ten clanek a ten kontrolel je velmi nestasne napsany. $_POST by mela byt promena vlozena z venci, treba pri construct. Uvnitr pouzivat globalni je spatne.

Editováno 13. května 8:47
 
Odpovědět  +1 13. května 8:46
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Peter Mlich
David Čápka:13. května 8:48

Práce s daty od uživatele je v režii kontroleru a určitě tedy není nešťastně napsaný, to si pleteš s modelem.

Odpovědět 13. května 8:48
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:13. května 8:54

Kontroler muze byt klidne inicializovany takto:
$x = new mujkontroler($_POS­T)
Podle mne je lepsi se vyhnout situaci, kdy pouzivas globalni promenou uvnitr. Muzes si usetrit spoustu problemu.

 
Odpovědět 13. května 8:54
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Peter Mlich
David Čápka:13. května 9:02

Nějak si neumím představit jaké problémy si mohu ušetřit, stejně se volá vždy jen jedna akce kontroleru v jeden čas. To bys musel z POST něco mazat a pak na to zapomenou v jiné akci nebo něco podobného, což se nikdy nestane. Nemám rád tohle hnidopíchání do tutoriálů pro začátečníky, že neobsahují v první lekci desetivrstvou architekturu a neuronovou síť. Je to tutoriál pro vysvětlení MVC architektury začátečníkům, na používání $_POST pro čtení dat odeslaných metodou POST není v kontroleru nic špatného. Kdyby jsi napsal, že je lepší řešení a postnul tenhle kód, tak no problem, ale psát pod tento článek, že je "velmi nešťastně napsaný" je docela mimo a ubližuje to jak autorovi, tak lidem, co se z toho učí.

Editováno 13. května 9:03
Odpovědět 13. května 9:02
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:13. května 9:20

Mne se to nechtelo vypisovat, protoze si myslim, ze s classy vetsi zkusenosti. Ja bych to napsal asi nejak takto nebo jinak.

<?php
class KontaktKontroler extends Kontroler
{
var $form_data;
        function __construct($form_data)
        {
        $this->form_data = $form_data;
        }
        public function zpracuj($parametry)
        {
                $form = $this->form_data;
                $this->hlavicka = array(
                        'titulek' => 'Kontaktní formulář',
                        'klicova_slova' => 'kontakt, email, formulář',
                        'popis' => 'Kontaktní formulář našeho webu.'
                );

                if (isset($form["email"]))
                {
                        if ($form['rok'] == date("Y"))
                        {
                                $odesilacEmailu = new OdesilacEmailu();
                                $odesilacEmailu->odesli("[email protected]", "Email z webu", $form['zprava'], $form['email']);
                        }
                }

                $this->pohled = 'kontakt';
    }
}

---

<?php
class KontaktKontroler extends Kontroler
{
        public function zpracuj($form, $parametry)
        {
                $this->hlavicka = array(
                        'titulek' => 'Kontaktní formulář',
                        'klicova_slova' => 'kontakt, email, formulář',
                        'popis' => 'Kontaktní formulář našeho webu.'
                );

                if (isset($form["email"]))
                {
                        if ($form['rok'] == date("Y"))
                        {
                                $odesilacEmailu = new OdesilacEmailu();
                                $odesilacEmailu->odesli("[email protected]", "Email z webu", $form['zprava'], $form['email']);
                        }
                }

                $this->pohled = 'kontakt';
    }
}

Nebo to nazvat nejak rozumne, obecne. Zrovna mne nenapada nic lepsiho nez $form_data, $form, $post, $mail_form.

Ps nejsou tu ty edit. tlacitka. Aspon code by mohlo byt.

Editováno 13. května 9:21
 
Odpovědět  +2 13. května 9:20
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Peter Mlich
David Čápka:13. května 9:37

Tvoje řešení je hezký. Dále v navazujícím kurzu se to pak i podobně dělá (formuláře se wrappují do třídy a s POST se již nepracuje). Tady mi to přišlo ještě OK.

Odpovědět 13. května 9:37
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Alma Mater
Člen
Avatar
Odpovídá na Michal Šmahel
Alma Mater:17. května 4:11

Citujem z Lekcie 1

Pohled přijme data od kontroleru a vloží je do připravené šablony. Hotová stránka je zobrazena uživateli, který často o celé této kráse ani netuší :)

A kde je konkrétne napísané ako pohled prijme data od kontroleru?? Kontroler ukladá data do premenných to mi je jasné....

// Nastavení proměnných pro šablonu.... SmerovacKontroler si ukladá data z vnoreného kontroleru
                $this->data['titulek'] = $this->kontroler->hlavicka['titulek'];
                $this->data['popis'] = $this->kontroler->hlavicka['popis'];
                $this->data['klicova_slova'] = $this->kontroler->hlavicka['klicova_slova'];

Skôr vychádza že kontroler prijíma data a metodou vypisPohled() na premenné iba odkazuje ($this->data) a ($this->pohled). Pohled (Šablona) si premenne len dosadí...

Otazkou vlastne je, či je vôbec vhodne písat, že pohled prijíma data od kontrolera.Ked jedine kontroler prijíma data a ukladá ich do premennych a potom na ne odkazuje. Tým, že kontroler zobrazí vystúp, pohled o kontrolerovi nevie, čiže pohled nevie co ma prijat.... len vie co ma dosadiť. Preto sa mi zdá..ze medzi pohľadom a kontrolerom je to trochu abstraktné :-), alebo Davidove texty:-)?

Odpovědět 17. května 4:11
Kopírovanie je forma zdieľania informácii, bez autorských práv sa informácie nezadržiavajú - šíria sa tam kde treba..
Avatar
Michal Šmahel:18. května 14:17

Ahoj, bylo by lepší hned v původním příspěvku zmínit danou citaci, aby bylo jasné, co hodláš rozebírat. Navíc se jedná o 5. lekci, komentář patří tedy trochu jinam.

Pro úplné pochopení této problematiky je třeba znát princip funkčnosti include a require, tedy skládání souborů se zdrojovým kódem v PHP. Načtení pohledu a předání dat funguje právě na tomto principu. Zakládá to na tom, že když připojíš HTML soubor nebo soubor generující HTML kód, tento kód se přidá k tomu, co se odešle klientovi. Předání dat funguje tak, že se v kontroleru rozbalí pole s získanými daty od dílčích kontrolerů. Jelikož je PHP kód ve výsledku všechen v jednom souboru (include a require vlastně jen připojují obsah daného souboru k prvnímu souboru, který byl načten), jsou proměnné rozbalené v kontroleru dostupné i v šabloně.

Ještě tě zajímalo, jak řídící kontroler data získá. Je to poměrně jednoduché. Dílčí kontrolery (ty, které tento řídící vytvoří a zavolá na nich zpracování) získaná data ukládají do třídní vlastnosti $data (pole). Tato vlastnost je veřejná, je k ní tedy možnost přistupovat zvenčí - například z řídícího kontroleru. Dále je tu vlastnost $head, do níž dílčí kontrolery ukládají údaje do HTML hlavičky. Za funguje stejně. Řídící kontroler si jen data přečte z těchto vlastností a uloží si je do své vlastnosti data (samozřejmě dojde k jejich spojení). Z této vlastnosti jsou poté rozbaleny na jednotlivé proměnné (název klíče = název proměnné) a použity v šabloně.

David to v článku popisuje správně. Pro lepší pochopení architektury (MVC) využívá určité abstrakce, kdy nenazývá věci podle implementace, ale filozofie architektury. Implementaci však také podrobně popisuje, problém bych v tom neviděl.

Odpovědět 18. května 14:17
Nejdůležitější je motivace, ovšem musí být doprovázena činy.
Avatar
Odpovídá na Alma Mater
Michal Šmahel:18. května 14:20

Zapomněl jsem tě označit.

Odpovědět 18. května 14:20
Nejdůležitější je motivace, ovšem musí být doprovázena činy.
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 37. Zobrazit vše