Vánoční nadílka Vánoční nadílka
Až 80% zdarma! Předvánoční BLACK FRIDAY akce. Více informací

Lekce 8 - Jednoduchý redakční systém v Symfony - Administrace

PHP Symfony Základy Jednoduchý redakční systém v Symfony - Administrace

ONEbit hosting 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 Symfony - Výpis článku, jsme již vytvořili základní strukturu pro výpis článků. Dnes budeme pokračovat s tvorbou jejich administrace v redakčním systému postaveném na PHP frameworku Symfony.

Kontroler

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

src/Controller/Ar­ticleController­.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(string $url = null, Request $request): 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:
    paths: ['%kernel.project_dir%/templates']
    debug: '%kernel.debug%'
    strict_variables: '%kernel.debug%'

    # 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/for­m/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/arti­cle/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="//cdn.tinymce.com/4/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/arti­cle/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ůžete podívat na výsledek, zkusit si vypsat seznam článků a klidně je i nějak editovat. :)

Příště si v lekci Jednoduchý redakční systém v Symfony - Kontaktní formulář přidáme ještě ContactControler a příslušné šablony, čímž administraci článků v našem redakčním systému v Symfony dokončíme.


 

Stáhnout

Staženo 25x (13.36 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?
3 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 (9)

 

 

Komentáře

Avatar
Tomáš Daněk:26. září 8:39

Výpis článků nebude fungovat dokud do adreaáře public/ nenakopírujete soubor .htaccess z přiloženého archivu. Bez tohoto .htaccess souboru se už při zobrazení úvodní stránky korektně nenačte Symfony Toolbar. Bylo by dobré doplnit do textu. Děkuji

 
Odpovědět 26. září 8:39
Avatar
Jindřich Máca
Tým ITnetwork
Avatar
Odpovídá na Tomáš Daněk
Jindřich Máca:26. září 19:02

Ahoj, tohle je popsané už v článku s instalací projektu Lekce 2 - Instalace Symfony a IDE v sekci Směrování. Pokud chceš, aby Ti projekt správně fungoval na Apache serveru, měl by jsi nainstalovat apache-pack a to pomocí příkazu composer require symfony/apache-pack. Ten právě mimo jiné automaticky přidá onen soubor .htaccess do složky public/. Je to přesně popsáno i v oficiální dokumentaci. Ale tohle není nijak povinné, protože např. pokud by jsi chtěl rozjet projekt na Nginx serveru, budeš postupovat jinak. :)

 
Odpovědět 26. září 19:02
Avatar
Odpovídá na Jindřich Máca
Tomáš Daněk:26. září 21:13

Pardon, instalaci apache-pack jsem "přehlédl"...

 
Odpovědět 26. září 21:13
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 3 zpráv z 3.