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 8 - Jednoduchý redakční systém v Symfony - Administrace

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

Dnes do kontroleru přidáme akce pro vytváření, mazání a editaci článků.

Kontroler

Jelikož modelovou vrstvu v podobě entity a repositáře máme již nachystanou z minula, začneme rovnou od kontroleru.

src/Controller/ArticleController.php

Protože v Symfony můžeme mít více akcí v jednom kontroleru, budeme pokračovat v rozšiřování naší třídy ArticleController a přidáme do ní následující metody dalších akcí:

<?php

namespace App\Controller;

use App\Entity\Article;
use App\Repository\ArticleRepository;
use Doctrine\ORM\ORMException;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;

/**
 * Kontroler pro práci s články.
 * @package App\Controller
 */
class ArticleController extends AbstractController
{
    /** @var ArticleRepository Repositář pro správu článků. */
    private $articleRepository;

    /**
     * Konstruktor kontroleru pro práci s články.
     * @param ArticleRepository $articleRepository automaticky injektovaný repositář pro správu článků
     */
    public function __construct(ArticleRepository $articleRepository)
    {
        $this->articleRepository = $articleRepository;
    }

    /**
     * Načte a předá seznam všech článků do šablony.
     * @return Response HTTP odpověď
     * @Route("/seznam-clanku", name="article_list")
     */
    public function list(): Response
    {
        return $this->render('article/list.html.twig', ['articles' => $this->articleRepository->findAll()]);
    }

    /**
     * Odstraní článek podle jeho URL.
     * @param string|null $url URL článku
     * @return Response HTTP odpověď
     * @Route("/odstranit/{url}", name="remove_article")
     * @throws ORMException Jestliže nastane chyba při mazání článku.
     */
    public function remove(string $url = null): Response
    {
        $this->articleRepository->removeByUrl($url);
        $this->addFlash('notice', 'Článek byl úspěšně odstraněn.');
        return $this->redirectToRoute('article_list');
    }

    /**
     * Vytváří a zpracovává formulář pro editaci článku podle jeho URL.
     * @param string|null $url     URL článku
     * @param Request     $request HTTP požadavek
     * @return Response HTTP odpověď
     * @Route("/editor/{url}", name="article_editor")
     * @throws ORMException Jestliže nastane chyba při ukládání článku.
     */
    public function editor(Request $request, string $url = null): Response
    {
        if ($url) { // Pokud byla zadána URL, pokusí se načíst článek podle ní.
            if (!($article = $this->articleRepository->findOneByUrl($url))) {
                // Pokud se článek s danou URL nepodaří najít, vypíše chybovou hlášku a vytvoří nový s danou URL.
                $this->addFlash('warning', 'Článek se zadanou URL nebyl nalezen!');
                $article = (new Article())->setUrl($url);
            }
        } else $article = new Article(); // Jinak se nejedná o editaci článku a vytváří se nový článek.

        // Vytváření editačního formuláře podle entity článku.
        $editorForm = $this->createFormBuilder($article)
            ->add('title', null, ['label' => 'Titulek'])
            ->add('url', null, ['label' => 'URL'])
            ->add('description', null, ['label' => 'Popisek'])
            ->add('content', null, ['label' => 'Obsah', 'required' => false])
            ->add('submit', SubmitType::class, ['label' => 'Uložit článek'])
            ->getForm();

        // Zpracování editačního formuláře.
        $editorForm->handleRequest($request);
        if ($editorForm->isSubmitted() && $editorForm->isValid()) {
            $this->articleRepository->save($article);
            $this->addFlash('notice', 'Článek byl úspěšně uložen.');
            return $this->redirectToRoute('article', ['url' => $article->getUrl()]);
        }

        // Předání editačního formuláře do šablony.
        return $this->render('article/editor.html.twig', ['editorForm' => $editorForm->createView()]);
    }

    /**
     * Načte článek podle jeho URL a předá jej do šablony.
     * Pokud není zadaná URL, nastaví se jí hodnota pro výchozí článek.
     * @param Article $article článek
     * @return Response HTTP odpověď
     * @throws NotFoundHttpException Jestliže článek s danou URL nebyl nalezen.
     * @Route("/{url?%default_article_url%}", name="article")
     * @Entity("article", expr="repository.findOneByUrl(url)")
     */
    public function index(Article $article): Response
    {
        return $this->render('article/index.html.twig', ['article' => $article]);
    }
}

Nyní by asi bylo dobré si uvedený kód trochu popsat. V první řadě jsme přidali následující akce i s pravidly pro routování, které využívají našeho repositáře článků:

  • listAction() - Vypisuje seznam všech článků.
  • removeAction() - Odstraní vybraný článek.
  • editorAction() - Umožňuje vytvářet nové i editovat stávající články.

Dále jsme sjednotili získání repositáře pro správu článků pomocí DI napříč všemi těmito metodami a to pomocí principů OOP, konkrétně privátního atributu a konstruktoru.

Nakonec stojí asi za povšimnutí formulář pro vytváření a editaci článků, který jsme postavili na naší entitě Article, takže využívá jejích validačních pravidel a automaticky nám tak dovolí uložit pouze článek s validními daty.

Konfigurace

Ještě než se přesuneme k samotným šablonám, přidáme jednu drobnou vychytávku do konfigurace.

config/packages/twig.yaml

Naučíme totiž všechny formuláře v naší aplikaci používat výchozí Twig šablonu pro jejich vykreslování:

twig:
    default_path: '%kernel.project_dir%/templates'

    # Nastaví všem formulářům v aplikaci tuto šablonu pro vykreslování.
    form_themes:
        - 'form/fields.html.twig'

Šablony

Nyní se podíváme na šablony k jednotlivým akcím.

templates/form/fields.html.twig

Začneme definicí oné šablony pro vykreslení jednoho obecného formulářového elementu:

{# Vlastní definice vzhledu jednoho řádku formuláře. #}
{% block form_row %}
    <div>
        {{ form_errors(form) }}<br>
        {{ form_label(form) }}<br>
        {{ form_widget(form) }}
    </div>
{% endblock form_row %}

Šablonu si samozřejmě můžete upravit dle libosti k dosažení vašeho oblíbeného vzhledu.

templates/article/editor.html.twig

Nyní následuje šablona pro editor článků. Zde si povšimněte jak jednoduše jsme zařídili vykreslení formuláře i s naší vlastní šablonou a dále způsobu přidávání dalších JavaScript knihoven:

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

{% block title %}Editor{% endblock %}
{% block description %}Editor článků.{% endblock %}
{% block body %}
    {# Formulář pro editaci článku. #}
    {{ form(editorForm) }}
{% endblock %}

{% block javascripts %}
    {{ parent() }}
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/tinymce/5.5.1/tinymce.min.js"></script>
    <script type="text/javascript">
        tinymce.init({
            selector: '#form_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>
{% endblock %}

templates/article/list.html.twig

Dále přidáme šablonu pro výpis článků:

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

{% block title %}Výpis článků{% endblock %}
{% block description %}Výpis všech článků.{% endblock %}
{% block body %}
    <table>
        {% for article in articles %}
            <tr>
                <td>
                    <h2><a href="{{ path('article', {'url': article.url}) }}">{{ article.title }}</a></h2>
                    {{ article.description }}
                    <br/>
                    <a href="{{ path('article_editor', {'url': article.url}) }}">Editovat</a>
                    <a href="{{ path('remove_article', {'url': article.url}) }}">Odstranit</a>
                </td>
            </tr>
        {% endfor %}
    </table>
{% endblock %}

templates/base.html.twig

Na závěr přidáme ještě odkazy do výchozí šablony. Nebudu ji sem již vypisovat znovu celou, pouze změny:

...
<nav>
    <ul>
        <li><a href="{{ path('article') }}">Úvod</a></li>
        <li><a href="{{ path('article_list') }}">Seznam článků</a></li>
        <li><a href="#">Kontakt</a></li>
    </ul>
</nav>
...

Nyní se již můžeme podívat na výsledek. Zkusíme si editovat úvodní článek kliknutím na odkaz "Editovat":

Základy frameworku Symfony pro PHP

Můžeme si článek zkusit i následně odebrat (ale pozor, zatím nemáme metodu pro přidání článku):

Základy frameworku Symfony pro PHP

Pro dnešní lekci to ale bude vše :)

V další lekci, Jednoduchý redakční systém v Symfony - Kontaktní formulář, přidáme ContactControler a příslušné šablony.


 

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 72x (55.8 kB)
Aplikace je včetně zdrojových kódů v jazyce PHP

 

Předchozí článek
Jednoduchý redakční systém v Symfony - Výpis článku
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 - Kontaktní formulář
Článek pro vás napsal Jindřich Máca
Avatar
Uživatelské hodnocení:
19 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