Lekce 8 - Jednoduchý redakční systém v Nette - Dokončení administrace

PHP Nette Framework Základy Jednoduchý redakční systém v Nette - Dokončení administrace

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 Nette - Administrace, jsme rozpracovali administraci článků. Dnes ji spolu s kontaktním formulářem dokončíme.

Presentery

Začneme dokončením presenterů z minula.

app/CoreModule/pre­senters/Contac­tPresenter.php

Přidáme tak ještě jeden presenter pro kontaktní formulář:

<?php

namespace App\CoreModule\Presenters;

use App\Presenters\BasePresenter;
use Nette\Application\UI\Form;
use Nette\Mail\IMailer;
use Nette\Mail\Message;
use Nette\Mail\SendException;
use Nette\Utils\ArrayHash;

/**
 * Presenter pro kontaktní formulář.
 * @package App\CoreModule\Presenters
 */
class ContactPresenter extends BasePresenter
{
        /** @var string Kontaktní email, na který se budou posílat emaily z kontaktního formuláře. */
        private $contactEmail;

        /** @var IMailer Služba Nette pro odesílání emailů. */
        private $mailer;

        /**
         * Konstruktor s nastavením kontaktního emailu a injektovanou Nette službou pro odesílání emailů.
         * @param string  $contactEmail kontaktní email
         * @param IMailer $mailer       automaticky injektovaná Nette služba pro odesílání emailů
         */
        public function __construct($contactEmail, IMailer $mailer)
        {
                parent::__construct();
                $this->contactEmail = $contactEmail;
                $this->mailer = $mailer;
        }

        /**
         * Vytváří a vrací kontaktní formulář.
         * @return Form kontaktní formulář
         */
        protected function createComponentContactForm()
        {
                $form = new Form;
                $form->getElementPrototype()->setAttribute('novalidate', true);
                $form->addEmail('email', 'Vaše emailová adresa')->setRequired();
                $form->addText('y', 'Zadejte aktuální rok')->setOmitted()->setRequired()
                        ->addRule(Form::EQUAL, 'Chybně vyplněný antispam.', date("Y"));
                $form->addTextArea('message', 'Zpráva')->setRequired()
                        ->addRule(Form::MIN_LENGTH, 'Zpráva musí být minimálně %d znaků dlouhá.', 10);
                $form->addSubmit('send', 'Odeslat');

                // Funkce se vykonaná při úspěšném odeslání kontaktního formuláře a odešle email.
                $form->onSuccess[] = function (Form $form, ArrayHash $values) {
                        try {
                                $mail = new Message;
                                $mail->setFrom($values->email)
                                        ->addTo($this->contactEmail)
                                        ->setSubject('Email z webu')
                                        ->setBody($values->message);
                                $this->mailer->send($mail);
                                $this->flashMessage('Email byl úspěšně odeslán.');
                                $this->redirect('this');
                        } catch (SendException $e) {
                                $this->flashMessage('Email se nepodařilo odeslat.');
                        }
                };

                return $form;
        }
}

Zde si všimněte především použití Nette knihovny pro odesílání emailů z formuláře.

app/CoreModule/con­fig/config.ne­on

Dále nesmíme zapomenout předat konfiguraci kontaktního emailu do našeho nového presenteru:

#
# Konfigurační soubor pro CoreModule.
#
parameters:
        defaultArticleUrl: 'uvod'          # URL výhozího článku
        contactEmail: '[email protected]' # Kontaktní email


# Nastavení služeb pro CoreModule.
services:
        # Definice vlastních služeb dále přístupných pomocí DI.
        - App\CoreModule\Model\ArticleManager

        # Předání nastavení při vytváření služeb presenterů.
        - App\CoreModule\Presenters\ArticlePresenter(%defaultArticleUrl%)
        - App\CoreModule\Presenters\ContactPresenter(%contactEmail%)

app/config/con­fig.neon

Pokud jste pozorně četli kód, všimli jste si, že u tvorby formulářů v metodě setRequired() není vyplněna chybová hláška. To je z toho důvodu, že nám bude stačit všude stejná a tu si globálně nastavíme v hlavním konfiguračním souboru připsáním následujících řádků:

...
# Nastavení výchozích chybových hlášek pro formuláře.
forms:
        messages:
                REQUIRED: 'Povinné pole.'
                EMAIL: 'Neplatná emailová adresa.'
...

app/router/Rou­terFactory.php

Nakonec musíme opět upravit routování, aby naše aplikace brala v potaz nové presentery a jejich akce. Ukážeme si zde také rovnou příklad překladu českých URL adres na anglické názvy akcí:

<?php

namespace App;

use Nette\Application\IRouter;
use Nette\Application\Routers\Route;
use Nette\Application\Routers\RouteList;
use Nette\StaticClass;

/**
 * Továrna na routovací pravidla.
 * Řídí směrování a generovaní URL adres v celé aplikaci.
 * @package App
 */
class RouterFactory
{
        use StaticClass;

        /**
         * Vytváří a vrací seznam routovacích pravidel pro aplikaci.
         * @return IRouter výsledný router pro aplikaci
         */
        public static function createRouter()
        {
                $router = new RouteList;
                $router[] = new Route('kontakt', 'Core:Contact:default');
                $router[] = new Route('administrace', 'Core:Administration:default');
                $router[] = new Route('<action>[/<url>]', [
                        'presenter' => 'Core:Article',
                        'action' => [
                                Route::FILTER_STRICT => true,
                                Route::FILTER_TABLE => [
                                        // řetězec v URL => akce presenteru
                                        'seznam-clanku' => 'list',
                                        'editor' => 'editor',
                                        'odstranit' => 'remove'
                                ]
                        ]
                ]);
                $router[] = new Route('[<url>]', 'Core:Article:default');
                return $router;
        }
}

Pokud se divíte, proč mají některé presentery svojí vlastní routu, tak je to z toho důvodu, že potřebujeme rozlišit mezi URL článku a názvem presenteru, protože obě mají stejný tvar - /presenter vs. /url. V tomto případě tedy vždy dostane přednost název presenteru před vykreslením URL článku.

Šablony

Nyní se můžeme podívat zase na šablony (templates).

app/templates/@la­yout.latte

Zde pouze doplníme odkazy na jednotlivé presentery a jejich akce pomocí Latte maker a přidáme odkaz na administrační rozhraní do patičky. Nebudu sem vypisovat již znovu celou šablonu, pouze provedené změny:

...
<ul>
        <li><a n:href=:Core:Article:>Úvod</a></li>
        <li><a n:href=:Core:Article:list>Seznam článků</a></li>
        <li><a n:href=:Core:Contact:>Kontakt</a></li>
</ul>
...
<footer>
        <p>
                Ukázkový tutoriál pro jednoduchý redakční systém v Nette z programátorské sociální sítě
                <a href="http://www.itnetwork.cz" target="_blank">itnetwork.cz</a>.
                <a n:href=:Core:Administration:>Administrace</a>
        </p>
</footer>
...

app/CoreModule/tem­plates/Article/lis­t.latte

Přidáme si šablonu pro výpis seznamu článků:

{block title}Výpis článků{/block}
{block description}Výpis všech článků.{/block}
{block content}
<table>
        <tr n:foreach="$articles as $article">
                <td>
                        <h2><a n:href="Article: $article->url">{$article->title}</a></h2>
                        {$article->description}
                        <br>
                        <a n:href="editor $article->url">Editovat</a>
                        <a n:href="remove $article->url">Odstranit</a>
                </td>
        </tr>
</table>

app/CoreModule/tem­plates/Article/e­ditor.latte

Dále přidáme šablonu pro editor článků. Zde si povšimněte jak jednoduše jsme zařídili vykreslení formuláře a také způsobu přidávání dalších JavaScript knihoven:

{block title}Editor{/block}
{block description}Editor článků.{/block}
{block content}
        {* Formulář pro editaci. *}
        {control editorForm}
{/block}

{block scripts}
        {include parent}
        <script type="text/javascript" src="//cdn.tinymce.com/4/tinymce.min.js"></script>
        <script type="text/javascript">
                tinymce.init({
                        selector: 'textarea[name=content]',
                        plugins: [
                                'advlist autolink lists link image charmap print preview anchor',
                                'searchreplace visualblocks code fullscreen',
                                'insertdatetime media table contextmenu paste'
                        ],
                        toolbar: 'insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image',
                        entities: '160,nbsp',
                        entity_encoding: 'raw'
                });
        </script>
{/block}

app/CoreModule/tem­plates/Adminis­tration/defau­lt.latte

Následuje šablona pro administrační rozhraní:

{block title}Administrace webu{/block}
{block description}Administrace webu.{/block}
{block content}
<p>Vítejte v administraci!</p>
<h2><a n:href=Article:editor>Editor článků</a></h2>
<h2><a n:href=Article:list>Seznam článků</a></h2>

app/CoreModule/tem­plates/Contac­t/default.lat­te

A na závěr šablona pro stránku s kontaktním formulářem:

{block title}Kontaktní formulář{/block}
{block description}Kontaktní formulář.{/block}
{block content}
<p>Kontaktujte nás odesláním formuláře níže.</p>
{* Formulář pro kontakt. *}
{control contactForm}
Stránka s kontaktním formulářem

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

Nyní v rámci 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 Nette - Model uživatelů, začneme rozšířením databáze a přidáním modelu uživatelů.


 

Stáhnout

Staženo 469x (1.18 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?
12 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 (4)

 

 

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

Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Jindřich Máca:21.2.2017 20:18

Myslím, že to jsou trochu popletené pojmy. Za výpis článků přeci vůbec není zodpovědný soubor Latte šablony, ale samotná akce presenteru. Šablona pak pouze slouží k reprezentaci výstupu dané akce do HTML podoby. Konvence jsou pak v tom, jaká šablona se mapuje na kterou příslušnou akci presenteru. :)

Pro pochopení problematiky doporučuji kouknout hned na první díl seriálu (http://www.itnetwork.cz/…eworku-nette), kde je vysvětlen životní cyklus stránky v Nette, včetně obrázku. ;)

 
Odpovědět 21.2.2017 20:18
Avatar
Vakos
Redaktor
Avatar
Odpovídá na Jindřich Máca
Vakos:21.2.2017 20:31

Prošel jsem si to a snad už vím. Nyní ale nevím jak to změnit v Presenteru. Aktuálně je tam takovýto řádek

$this->template->articles = $this->articleManager->getArticles();

Jak napsat tedy nový řádek například pro šablonu page.latte? Díval jsem se i na nette.org, ale moudrý z toho moc nejsem ...

Odpovědět 21.2.2017 20:31
"Jediný způsob, jak dělat skvělou práci, je milovat to, co děláte. Pokud jste to ještě nenašli, hledejte dál. Ne...
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Vakos
Jindřich Máca:21.2.2017 20:46

Tohle je kód, co právě předává příslušná data článků do automaticky (podle konvencí) namapované Latte šablony. Vůbec to nesouvisí s tím, jaká šablona se použije, jde pouze o to předávání dat.

Pokud Ti to moc nedává smysl, tak hned na začátku seriálu je napsané, že je potřeba umět dobře OOP v PHP a vědět něco o třívrstvé MVP (MVC) architektuře. Možná bych tedy začal tam. ;)

 
Odpovědět 21.2.2017 20:46
Avatar
Karl
Člen
Avatar
Odpovídá na Jindřich Máca
Karl:22.2.2017 9:42

Jindro, prosím mohl bys juknout na můj poslední dotaz z 15. února? Díky

 
Odpovědět 22.2.2017 9:42
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Karl
Jindřich Máca:22.2.2017 22:39

Promiň, já jsem Tvůj příspěvek četl, ale považoval jsem ho spíše za konstatování, protože v něm nevidím žádnou otázku a před tím jsi ještě uváděl, že Ti to při nějakém nastavení funguje. :D

Shrnul bych to asi takhle, pokud to nefunguje na hostingu, kde vlastně nemáš možnost si nic přenastavit, tak asi bude opravdu potřeba předělat příslušné inserty. :(

Jak to udělat "dobře" můžeš najít třeba tady - http://stackoverflow.com/…-primary-key

 
Odpovědět 22.2.2017 22:39
Avatar
SolusLupusUmbra
Redaktor
Avatar
SolusLupusUmbra:11.7.2017 23:13

v routeru máš new Route("[<acti­on>/][url]",.­....)
nebylo by výhodnější použít new Route( "[<module>/] [<presenter>/<ac­tion>] [<url>]",... )?
neposkytlo by to uživateli příliš informací o struktuře?
pokud bych to použil, stačilo by routovat jen výchozí stránku?
Díky,

 
Odpovědět 11.7.2017 23:13
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na SolusLupusUmbra
Jindřich Máca:11.7.2017 23:25

Můžeš to klidně upravit podle sebe, pokud chceš. Potencionálně může nastat pouze rozdíl v URL adresách, což vlastně stejně záleží čistě na Tobě. ;)

P.S.: Za případné chyby ale neručím. :D

Editováno 11.7.2017 23:26
 
Odpovědět 11.7.2017 23:25
Avatar
Vaclav Hrouda:4. srpna 18:18

Tak jsem si stáhl přiložený soubor a:

Fatal error: Cannot use 'Object' as class name as it is reserved in /mnt/drive/www/net­te/rs-nette/vendor/net­te/utils/src/U­tils/Object.php on line 54

Myslím že takhle by to vypadat nemělo...

 
Odpovědět 4. srpna 18:18
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Vaclav Hrouda
David Čápka:4. srpna 18:48

Ahoj, autor Nette se rozhodl použít slovo object a proto verze 2.3 přestala od PHP 7 fungovat. Jsme v tom tedy tak trochu nevinně. Na aktualizaci kurzu pro opravené Nette se pracuje. Řešením je buď downgrade PHP na verzi 5 nebo proklikat diskuze lekcí, kde se řeší jak to opravit.

Editováno 4. srpna 18:49
Odpovědět  +1 4. srpna 18: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
David Čápka
Tým ITnetwork
Avatar
David Čápka:6. srpna 13:25

Aktualizováno pro Nette 2.4.

Odpovědět 6. srpna 13:25
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! :)
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 50. Zobrazit vše