IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
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 7 - Jednoduchý redakční systém v Nette - Administrace

V minulé lekci, Jednoduchý redakční systém v Nette - Výpis článku, jsme vytvořili základní strukturu pro výpis článků.

Dnes se vrhneme do šablon. Tím výpis zprovozníme a budeme pokračovat s tvorbou jejich administrace.

Šablony

Nyní je tedy čas podívat se na zoubek šablonám (templates). Opět zde můžeme smazat celou složku app/templates/Homepage/, protože stejně jako třídu HomepagePresenter ji už nebudeme dále potřebovat.

app/templates/@layout.latte

Samozřejmě nezačneme ničím jiným než úpravou celkového vzhledu naší aplikace, který v tomto případě zajišťuje Latte šablona @layout.latte, opět předpřipravená v sandboxu, ze kterého vycházíme:

{**
 * @param string   $basePath web base path
 * @param array    $flashes  flash messages
 *}

{import 'components/form.latte'}

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">

    <title>{ifset title}{include title|stripHtml} | {/ifset}Nette Sandbox</title>

    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <link rel="stylesheet" href="{$basePath}/css/style.css">
    {block head}{/block}
</head>

<body>
    <header>
        <h1>Jednoduchý redakční systém v Nette</h1>
    </header>
    <div class=container>
        {* Výpis flash zpráv. *}
        <div n:foreach="$flashes as $flash" n:class="alert, 'alert-' . $flash->type">{$flash->message}</div>

        <nav>
            <ul>
                <li><a n:href=:Core:Article:>Úvod</a></li>
                <li><a href="#">Seznam článků</a></li>
                <li><a href="#">Kontakt</a></li>
            </ul>
        </nav>

        <br style="clear: both;">
        <article>
            <header>
                <h1>{include title}</h1>
            </header>
            <section>
                {include content} {* Vložení obsahu do šablony. *}
            </section>
        </article>
    </div>

    <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>
        </p>
    </footer>

    {block scripts}
        <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
        <script src="https://nette.github.io/resources/js/3/netteForms.min.js"></script>
        <script src="{$basePath}/js/main.js"></script>
    {/block}
</body>
</html>

app/CoreModule/templates/Article/default.latte

Nakonec vytvoříme složku Article/ pro šablony našeho ArticlePresenter v CoreModule a do ní přidáme soubor default.latte jako šablonou pro jeho výchozí akci renderDefault(). Samotná šablona je relativně jednoduchá:

{block title}{$article->title}{/block}
{block description}{$article->description}{/block}
{block content}
{$article->content|noescape}

Nyní si již můžeme zkusit web spustit a měli bychom vidět úvodní stránku. Je to jistě příjemný pocit po tom, co jsme změnili tolik kódu, že? :)

Úvodní stránka redakčního systému v Nette frameworku - Základy Nette frameworku

Úplný základ máme zprovozněný, nyní se podíváme hlouběji do CoreModule a to konkrétně na administraci článků ;)

Presentery

Model máme již nachystaný z minula, takže začneme rovnou od presenterů.

app/CoreModule/Presenters/ArticlePresenter.php

Jelikož v Nette můžeme mít více akcí v jednom presenteru, budeme pokračovat v rozšiřování naší třídy ArticlePresenter a přidáme do ní následující metody dalších akcí:

<?php

declare(strict_types=1);

namespace App\CoreModule\Presenters;

use App\CoreModule\Model\ArticleManager;
use App\Presenters\BasePresenter;
use Nette\Application\AbortException;
use Nette\Application\BadRequestException;
use Nette\Application\UI\Form;
use Nette\Database\UniqueConstraintViolationException;
use Nette\Utils\ArrayHash;

/**
 * Presenter pro vykreslování článků.
 * @package App\CoreModule\Presenters
 */
class ArticlePresenter extends BasePresenter
{
    /** @var string URL výchozího článku. */
    private string $defaultArticleUrl;

    /** @var ArticleManager Model pro správu s článků. */
    private ArticleManager $articleManager;

    /**
     * Konstruktor s nastavením URL výchozího článku a injektovaným modelem pro správu článků.
     * @param string         $defaultArticleUrl URL výchozího článku
     * @param ArticleManager $articleManager    automaticky injektovaný model pro správu článků
     */
    public function __construct(string $defaultArticleUrl, ArticleManager $articleManager)
    {
        parent::__construct();
        $this->defaultArticleUrl = $defaultArticleUrl;
        $this->articleManager = $articleManager;
    }

    /**
     * Načte a předá článek do šablony podle jeho URL.
     * @param string|null $url URL článku
     * @throws BadRequestException Jestliže článek s danou URL nebyl nalezen.
     */
    public function renderDefault(string $url = null)
    {
        if (!$url) $url = $this->defaultArticleUrl; // Pokud není zadaná URL, vezme se URL výchozího článku.

        // Pokusí se načíst článek s danou URL a pokud nebude nalezen vyhodí chybu 404.
        if (!($article = $this->articleManager->getArticle($url)))
            $this->error(); // Vyhazuje výjimku BadRequestException.

        $this->template->article = $article; // Předá článek do šablony.
    }

    /** Načte a předá seznam článků do šablony. */
    public function renderList()
    {
        $this->template->articles = $this->articleManager->getArticles();
    }

    /**
     * Odstraní článek.
     * @param string|null $url URL článku
     * @throws AbortException
     */
    public function actionRemove(string $url = null)
    {
        $this->articleManager->removeArticle($url);
        $this->flashMessage('Článek byl úspěšně odstraněn.');
        $this->redirect('Article:list');
    }

    /**
     * Vykresluje formulář pro editaci článku podle zadané URL.
     * Pokud URL není zadána, nebo článek s danou URL neexistuje, vytvoří se nový.
     * @param string|null $url URL adresa článku
     */
    public function actionEditor(string $url = null)
    {
        if ($url) {
            if (!($article = $this->articleManager->getArticle($url)))
                $this->flashMessage('Článek nebyl nalezen.'); // Výpis chybové hlášky.
            else $this['editorForm']->setDefaults($article); // Předání hodnot článku do editačního formuláře.
        }
    }

    /**
     * Vytváří a vrací formulář pro editaci článků.
     * @return Form formulář pro editaci článků
     */
    protected function createComponentEditorForm()
    {
        // Vytvoření formuláře a definice jeho polí.
        $form = new Form;
        $form->addHidden('article_id');
        $form->addText('title', 'Titulek')->setRequired();
        $form->addText('url', 'URL')->setRequired();
        $form->addText('description', 'Popisek')->setRequired();
        $form->addTextArea('content', 'Obsah');
        $form->addSubmit('save', 'Uložit článek');

        // Funkce se vykonaná při úspěšném odeslání formuláře a zpracuje zadané hodnoty.
        $form->onSuccess[] = function (Form $form, ArrayHash $values) {
            try {
                $this->articleManager->saveArticle($values);
                $this->flashMessage('Článek byl úspěšně uložen.');
                $this->redirect('Article:', $values->url);
            } catch (UniqueConstraintViolationException $e) {
                $this->flashMessage('Článek s touto URL adresou již existuje.');
            }
        };

        return $form;
    }
}

Zde bych upozornil především na způsob předávání výchozích hodnot do editačního formuláře a hlavně na to, že se úkon provádí v metodě actionEditor(), nikoliv v renderEditor(). Vyplývá to z životního cyklu akce Nette presenteru.

Dále si všimněte použití Nette knihovny pro vytvoření editačního formuláře, což nám, mimo např. bezpečnosti, v šabloně následně ušetří spoustu kódu při jeho vykreslování ;)

app/CoreModule/Presenters/AdministrationPresenter.php

Ještě než dnes skončíme s presentery, vytvoříme si jeden prázdný pro administrační sekci. Bude prázdný, protože, že v tuto chvíli v podstatě nepotřebujeme do jeho šablony nic předávat:

<?php

declare(strict_types=1);

namespace App\CoreModule\Presenters;

use App\Presenters\BasePresenter;

/**
 * Presenter pro vykreslování administrační sekce.
 * @package App\CoreModule\Presenters
 */
class AdministrationPresenter extends BasePresenter
{
}

Pro dnešní lekci to bude vše.

V další lekci, Jednoduchý redakční systém v Nette - Dokončení administrace, si přidáme presenter pro kontaktní formulář a poté také všechny chybějící šablony. Tak administraci článků v našem redakčním systému dokončíme :)


 

Předchozí článek
Jednoduchý redakční systém v Nette - Výpis článku
Všechny články v sekci
Základy Nette frameworku
Přeskočit článek
(nedoporučujeme)
Jednoduchý redakční systém v Nette - Dokončení administrace
Článek pro vás napsal Jindřich Máca
Avatar
Uživatelské hodnocení:
49 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