Vánoční nadílka Vánoční nadílka
Vánoční akce! Daruj lepší budoucnost blízkým nebo sobě. Až +50 % zdarma na dárkové poukazy. Více informací

Lekce 9 - Jednoduchý redakční systém v Symfony - Kontaktní formulář

PHP Symfony Základy Jednoduchý redakční systém v Symfony - Kontaktní formulář

Unicorn College ONEbit hosting 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, Jednoduchý redakční systém v Symfony - Administrace, jsme rozpracovali administraci. Dnes ji spolu s kontaktním formulářem dokončíme.

Model

Opět začneme hezky od modelu.

src/Entity/Con­tactMessage.php

Nejdříve vytvoříme entitu reprezentující zprávu z kontaktního formuláře, na které ho poté postavíme. Vypadat bude takto:

<?php

namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;

/**
 * Reprezentuje kontaktní emailovou zprávu.
 * @package App\Entity
 */
class ContactMessage
{
    /**
     * @var string Emailová adresa odesílatele.
     * @Assert\NotBlank(message = "Emailová adresa nemůže být prázdná!")
     * @Assert\Email(message="'{{ value }}' není validní emailová adresa!")
     */
    private $email;

    /**
     * @var string Obsah zprávy.
     * @Assert\NotBlank(message = "Obsah zprávy nemůže být prázdný!")
     * @Assert\Length(min=10, minMessage="Zpráva musí být minimálně {{ limit }} znaků dlouhá!")
     */
    private $message;

    /**
     * Getter pro email odesílatele.
     * @return null|string email odesílatele
     */
    public function getEmail(): ?string
    {
        return $this->email;
    }

    /**
     * Setter pro email odesílatele.
     * @param string $email email odesílatele
     * @return ContactMessage sebe
     */
    public function setEmail(string $email): self
    {
        $this->email = $email;
        return $this;
    }

    /**
     * Getter pro obsah zprávy.
     * @return null|string obsah zprávy
     */
    public function getMessage(): ?string
    {
        return $this->message;
    }

    /**
     * Getter pro obsah zprávy.
     * @param string $message obsah zprávy
     * @return ContactMessage sebe
     */
    public function setMessage(string $message): self
    {
        $this->message = $message;
        return $this;
    }
}

Kontroler

Dále si vytvoříme nový kontroler pro kontaktní stránku.

src/Controller/Con­tactController­.php

Výchozí akce pro vykreslení kontaktní stránky s formulářem bude vypadat následovně:

<?php

namespace App\Controller;

use App\Entity\ContactMessage;
use Swift_Mailer;
use Swift_Message;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Validator\Constraints\EqualTo;
use Symfony\Component\Validator\Constraints\NotBlank;

/**
 * Kontroler pro kontaktní formulář.
 * @package App\Controller
 */
class ContactController extends AbstractController
{
    /**
     * Vytváří a zpracovává kontaktní formulář.
     * @param Swift_Mailer $mailer  služba pro posílání emailů
     * @param Request      $request HTTP požadavek
     * @return Response HTTP odpověď
     * @Route("/kontakt", name="contact")
     */
    public function index(Swift_Mailer $mailer, Request $request): Response
    {
        // Vytváření kontaktního formuláře pro novou zprávu.
        $contactMessage = new ContactMessage();
        $contactForm = $this->createFormBuilder($contactMessage)
            ->add('email', null, ['label' => 'Vaše emailová adresa'])
            ->add('y', TextType::class, [
                'label' => 'Zadejte aktuální rok',
                'mapped' => false,
                'constraints' => [
                    new NotBlank(['message' => 'Pole pro aktuální rok nemůže být prázdné!']),
                    new EqualTo(['value' => date("Y"), 'message' => 'Chybně vyplněný antispam!'])
                ]
            ])
            ->add('message', TextareaType::class, ['label' => 'Zpráva'])
            ->add('submit', SubmitType::class, ['label' => 'Odeslat'])
            ->getForm();

        // Zpracování kontaktního formuláře.
        $contactForm->handleRequest($request);
        if ($contactForm->isSubmitted() && $contactForm->isValid()) {

            // Odeslání emailové zprávy.
            $mailer->send((new Swift_Message(
                'Email z webu',
                $contactMessage->getMessage(),
                'text/plain'
            ))->setFrom($contactMessage->getEmail()));

            $this->addFlash('notice', 'Email byl úspěšně odeslán.');
            return $this->redirectToRoute('contact');
        }

        return $this->render('contact/index.html.twig', ['contactForm' => $contactForm->createView()]);
    }
}

Zde si povšimněte především použití Symfony knihovny Swift Mailer pro poslání e-mailu po úspěšném odeslání formuláře.

Dále zde můžeme u kontaktního formuláře vidět přidání anti-spamového prvku, který automaticky validuje vyplnění aktuálního kalendářního roku.

Konfigurace

config/packages/swif­tmailer.yaml

Do nastavení doplníme e-mailovou adresu, na kterou se mají zprávy z kontaktního formuláře odesílat:

swiftmailer:
    url: '%env(MAILER_URL)%'
    spool: { type: 'memory' }

    # Email, na který se budou posílat všechny zprávy z kontaktního formuláře.
    delivery_addresses: ['[email protected]']

Ke správnému odesílání e-mailů je potřeba mít dobře nastavený mail server. Pokud nevíte, jak si jej nastavit na lokálním serveru, můžete tuto funkcionalitu vyzkoušet na vašem webhostingu.

Šablony

Nyní se můžeme přesunout na šablony.

templates/con­tact/index.html­.twig

Začneme šablonou pro stránku s kontaktním formulářem:

{% extends 'base.html.twig' %}

{% block title %}Kontaktní formulář{% endblock %}
{% block description %}Kontaktní formulář.{% endblock %}
{% block body %}
    <p>Kontaktujte nás odesláním formuláře níže.</p>
    {# Kontaktní formulář. #}
    {{ form(contactForm) }}
{% endblock %}

templates/admi­nistration/in­dex.html.twig

Dále vytvoříme úplně samostatnou šablonu, která bude pouze zahrnovat odkazy pro administrační rozhraní:

{% extends 'base.html.twig' %}

{% block title %}Administrace webu{% endblock %}
{% block description %}Administrace webu.{% endblock %}
{% block body %}
    <p>Vítejte v administraci!</p>
    <h2><a href="{{ path('article_editor') }}">Editor článků</a></h2>
    <h2><a href="{{ path('article_list') }}">Seznam článků</a></h2>
{% endblock %}

templates/base­.html.twig

A na závěr šablona pro celkový vzhled, kde pouze opět přidáme odkazy na nové akce:

...
<ul>
    <li><a href="{{ path('homepage') }}">Úvod</a></li>
    <li><a href="{{ path('article_list') }}">Seznam článků</a></li>
    <li><a href="{{ path('contact') }}">Kontakt</a></li>
</ul>
...
<footer>
    <p>
        Ukázkový tutoriál pro jednoduchý redakční systém v Symfony z programátorské sociální sítě
        <a href="http://www.itnetwork.cz" target="_blank">itnetwork.cz</a>.
        <a href="{{ path('administration') }}">Administrace</a>
    </p>
</footer>
...

Routování

Možná jste si všimli, že jsme přidali šablonu administrace bez vytvoření příslušného kontroleru. To však není chyba nýbrž záměr. Nyní to vysvětlíme a ukážeme si, jak vše uvést do funkčního stavu ;)

V první řadě, routování v Symfony ve výchozím stavu funguje podle abecedního pořadí kontrolerů a pořadí metod jednotlivých akcí v nich. Proto jsme i index() v třídě ArticleController nechali jako poslední, protože "polyká" jakoukoliv URL a snaží se jí namapovat na adresu článku. Tento problém se teď ale přenáší i na ContactController, protože ArticleController je v abecedním pořadí zkrátka výše.

Tudíž musíme zamíchat s pořadím a dále vyřešit již zmíněnou situaci, kdy máme šablonu pro administraci, která vlastně ani kontroler nepotřebuje, je tzv. statická. K tomu všemu musíme upravit routování v rámci konfigurace, což jsi nyní ukážeme.

config/routes.yml

V konfiguračním souboru nastavíme následující routovací pravidla:

administration:
    path:         /administrace
    controller:   Symfony\Bundle\FrameworkBundle\Controller\TemplateController
    defaults:
        template: administration/index.html.twig

articles:
    resource: App\Controller\ArticleController
    type: annotation

Jak vidíte, nejdříve jsme vyřešili routování šablony pro administraci bez existujícího kontroleru a následně předefinovali routování kontroleru článků jako poslední v pořadí, přičemž je ponecháno jeho původního anotačního routování.

Gratuluji, právě vám běží jednoduché administrační rozhraní pro články v Symfony s kontaktním formulářem jako bonus. ;)

Stránka s kontaktním formulářem

Nyní, v rámci on-line kurzu, budeme dále pokračovat v rozšiřování administrace a začneme se věnovat zabezpečení našeho webu, což by mělo vyústit v plně funkční přihlašování a registraci uživatelů s definicí jejich práv, takže se určitě máte na co těšit. Konkrétně v příští lekci, Jednoduchý redakční systém v Symfony - Model uživatelů, začneme rozšířením databáze a přidáním modelové vrstvy uživatelů :)


 

Stáhnout

Staženo 43x (13.36 MB)
Aplikace je včetně zdrojových kódů v jazyce PHP

 

 

Článek pro vás napsal Jindřich Máca
Avatar
Jak se ti líbí článek?
4 hlasů
Autor se věnuje převážně webovým technologiím, ale má velkou zálibu ve všem vědeckém, nejen ze světa IT. :-)
Aktivity (9)

 

 

Komentáře

Avatar
Marek Pastorek:7.7.2017 15:17

Zdravim,

chcem sa spytat, nema byt v ContactControllery namiesto ->setBody($con­tactMessage->getEmail() pouzita funkcia getMessage()?
Inak velmi dobry serial.

 
Odpovědět 7.7.2017 15:17
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Marek Pastorek
Jindřich Máca:7.7.2017 17:38

Zdravím,

samozřejmě máš pravdu, chybička se vloudila. :D Hned to opravím. ;)

P.S.: Jsem rád, že se seriál líbí. :)

 
Odpovědět 7.7.2017 17:38
Avatar
Tomáš Daněk:27. září 8:01

Opravdu je tato lekce psaná pro Symfony 4?

 
Odpovědět 27. září 8:01
Avatar
Tomáš Daněk:27. září 8:05

Jsou následující prémiové lekce přepracované do Symfony 4?

 
Odpovědět 27. září 8:05
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Tomáš Daněk
Jindřich Máca:27. září 8:26

Tato a následující lekce nejsou zatím ještě předěláné do Symfony 4. Aktuálně se na tom pracuje. ;-)

 
Odpovědět 27. září 8:26
Avatar
Tomáš Daněk:28. listopadu 10:20

Je už alespoň nějaká lekce převedena do Symfony 4, případně lze nějak odhadnout termín dokončení?

 
Odpovědět 28. listopadu 10:20
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Tomáš Daněk
Jindřich Máca:28. listopadu 12:44

Ahoj, zrovna dnes byla schválena aktualizace tohoto dílu a další už jsou na cestě. :)

Editováno 28. listopadu 12:45
 
Odpovědět 28. listopadu 12:44
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 7 zpráv z 7.