C/C++ week November Black Friday
Black Friday je tu! Využij jedinečnou příležitost a získej až 80 % znalostí navíc zdarma! Více zde
Pouze tento týden sleva až 80 % na e-learning týkající se C/C++

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

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

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 1748x (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 (30)

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
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
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..
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
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.
Avatar
Alma Mater
Člen
Avatar
Alma Mater:13. června 4:06

Cely systém funguje napr. z podzlozky cms na localhost v XAMPP v3.22 , na adrese (http://localhost/cms) pri tychto zmenach:

1. V subore Kontroler.php iba pridame nazov zlozky do url:

public function presmeruj($url)
        {
                         // tu pridame nazov zlozky cms do url
                header("Location: /cms/$url");
                header("Connection: close");
        exit;
        }

2.V súbore SmerovacKontro­ler.php, doplnime:

private function parsujURL($url)
        { ...
// tu doplnime funkciu, ktora odstrani prvu hodnotu z pola,  v nasom pripade cms..
array_shift($rozdelenaCesta);
return $rozdelenaCesta;
}

3. V subore rozlozeni.phtml nastavime cestu ku korenovej zlozke:

<base href= "/cms/" />

... vsetko...plati aj pre webhosting

Poznamka: Zmeny v suboroch je lepsie vykonat cez NetBeans, pretoze klasicky Notepad pri zmenach v suboroch pridava biele znaky, alebo ine neviditelne znaky, ktore napr. pri ostrom webhosting budú vypisovat chybu 500. Treba sa ujistit.ci sa nepridavaju neviditelne znaky pri zmenach v suboroch.Pokial sa pridavaju system nebude fungovat...
Subor htacces nie je potrebne menit.Vynimocne mozete skusit odkomentovat # RewriteBase / ak by vam system na webhostingu nefungoval, osobne som to vsak nepotreboval. System funguje aj pod PHP 5.6, PHP 7.1 PHP 7.2, PHP 7.3

Odpovědět
13. června 4:06
Kopírovanie je forma zdieľania informácii, bez autorských práv sa informácie nezadržiavajú - šíria sa tam kde treba..
Avatar
Alma Mater
Člen
Avatar
Alma Mater:13. června 4:23

Ked chceme aby redakcny system fungoval na subdomene webhostingu napr. na adrese

http://cms.nazov_domeny.sk alebo https://cms.nazov_domeny.sk

1.V administracii webhostingu vytvorime korenovu zlozku pre subdomenu:cms­.nazov_domeny­.sk

2.V subore rozlozeni.phtml zmenime korenovu zlozku :

<base href="http://cms.nazov_domeny.sk/" />
// alebo
<base href="https://cms.nazov_domeny.sk/" />

......vsetko...

Editováno 13. června 4:26
Odpovědět
13. června 4:23
Kopírovanie je forma zdieľania informácii, bez autorských práv sa informácie nezadržiavajú - šíria sa tam kde treba..
Avatar
Odpovídá na Alma Mater
FiftypiSoftware:25. srpna 12:50

Ahoj, díky, toto jsem hledal. Zkoušel jsem x možností, ale array_shift($roz­delCesta); mě nenapadlo. Vždycky přesmerování skončilo chybou too_many_redirects.

 
Odpovědět
25. srpna 12:50
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 40. Zobrazit vše