Geek tričko zdarma Týden návrhu sw
Tričko zdarma! Stačí před dobitím bodů použít kód TRIKO15. Více informací zde
Využij až 80% slevu na kurzy Návrhu Software

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

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, 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 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 549x (1.17 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?
13 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. :-)
Předchozí článek
Jednoduchý redakční systém v Nette - Administrace
Všechny články v sekci
Základy Nette frameworku
Miniatura
Následující článek
Jednoduchý redakční systém v Nette - Model uživatelů
Aktivity (5)

 

 

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

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.8.2018 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.8.2018 18:18
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Vaclav Hrouda
David Čápka:4.8.2018 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.8.2018 18:49
Odpovědět  +1 4.8.2018 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.8.2018 13:25

Aktualizováno pro Nette 2.4.

Odpovědět 6.8.2018 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! :)
Avatar
Marty
Člen
Avatar
Marty:26.10.2018 23:22

Je normální, že načtení na localhostu je kolem 500 ms?

 
Odpovědět 26.10.2018 23:22
Avatar
AlenaZ
Člen
Avatar
AlenaZ:3. dubna 13:03

Service 'application.2' (type of App\CoreModule\Pre­senters\Article­Presenter): Parameter $defaultArticleUrl in App\CoreModule\Pre­senters\Article­Presenter::__con­struct() has no class type hint or default value, so its value must be specified.
Děkuji za pomoc.

 
Odpovědět 3. dubna 13:03
Avatar
patrik.valkovic
Šéfredaktor
Avatar
Odpovídá na AlenaZ
patrik.valkovic:3. dubna 13:22

Ahoj, nastavila jsi službu správně v konfiguračním souboru? Tj. defaultArticleUrl: 'uvod' do parametrů a - App\CoreModule\Presenters\ArticlePresenter(%defaultArticleUrl%) při vytváření služby? Viz. článek.

Editováno 3. dubna 13:23
Odpovědět 3. dubna 13:22
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
AlenaZ
Člen
Avatar
AlenaZ:3. dubna 14:27

Dokonce jsem si stáhla zip a chyba byla pořád:
app/CoreModule/con­fig/config.ne­on
parameters:
defaultArticleUrl: 'uvod' # URL výhozího článku
# Nastavení služeb pro CoreModule.
services:
# Definice vlastních služeb dále přístupných pomocí DI.
- App\CoreModule\Mo­del\ArticleMa­nager

# Předání nastavení při vytváření služeb presenterů.
- App\CoreModule\Pre­senters\Article­Presenter(%de­faultArticleUr­l%)

Bere to jedině tady
public function __construct($de­faultArticleUr­l='uvod',Arti­cleManager $articleManager)

V configu to nevidí.

 
Odpovědět 3. dubna 14:27
Avatar
AlenaZ
Člen
Avatar
Odpovídá na AlenaZ
AlenaZ:3. dubna 17:57

bootstrap.php

$configurator->addConfig(__DIR__ . '/CoreModule/config/config.neon');
 
Odpovědět 3. dubna 17:57
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 55. Zobrazit vše