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í.

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

V minulé lekci, Jednoduchý redakční systém v Symfony - Administrace, jsme si přidali do kontroleru akce pro vytváření, editaci a mazání.

Dnes si přidáme ContactControler pro kontakt a příslušné šablony.

Model

Opět začneme hezky od modelu.

src/Entity/ContactMessage.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/ContactController.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. Abychom mohli tuto třídu používat, musíme ji Swift Mailer bundle nejdříve nainstalovat pomocí tohoto příkazu:

composer require symfony/swiftmailer-bundle

Dále 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

Po instalaci balíčku Swift Mailer se nám vytvořil i konfigurační soubor.

config/packages/swiftmailer.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 svém webhostingu.

Šablony

Nyní se můžeme přesunout na šablony. Pokud nemáme vytvořenou složku contact/ v adresáři templates/, vytvoříme si ji.

templates/contact/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/administration/index.html.twig

Dále vytvoříme úplně samostatnou šablonu, která bude pouze zahrnovat odkazy pro administrační rozhraní, ,taktéž si pro ni vytvoříme složku:

{% 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') }}">Přidat článek</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 a konečně i administraci:

...
<ul>
    <li><a href="{{ path('article') }}">Ú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 metodu index() ve 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 můžeme vidět, 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í routování.

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

Základy frameworku Symfony pro PHP

Administrace:

Základy frameworku Symfony pro PHP

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.

V další 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ů :)


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 98x (60.36 kB)
Aplikace je včetně zdrojových kódů v jazyce PHP

 

Předchozí článek
Jednoduchý redakční systém v Symfony - Administrace
Všechny články v sekci
Základy frameworku Symfony pro PHP
Přeskočit článek
(nedoporučujeme)
Jednoduchý redakční systém v Symfony - Model uživatelů
Článek pro vás napsal Jindřich Máca
Avatar
Uživatelské hodnocení:
16 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