BF Summer sales
Pouze tento týden sleva až 80 % na HTML & CSS a JavaScript
80 % bodů zdarma na online výuku díky naší Letní akci!

Lekce 7 - Jednoduchý redakční systém v Laravel - Výpis článku

Minulou lekci, Jednoduchý redakční systém v Laravel - Migrace, jsme věnovali migracím a vytvořili jsme si modelovou vrstvu pro články.

Jak jsem slíbil, dnes budeme v PHP Laravel tutoriálu pokračovat v tvorbě kontroleru a zprovozníme si zobrazení článku.

Routování

Začneme nejdříve tím, že si definujeme routy pro články. Otevřeme si soubor routes/web.php a odstraníme výchozí routu pro hlavní stránku, jelikož ji zatím v našem projektu nebudeme potřebovat. Místo ní si definujeme, že námi vytvořený CRUD kontroler má zpracovávat požadavky na články:

Route::resource('article', 'ArticleController');

Metodou resource() jsme definovali routy pro všechny CRUD akce kontroleru. Již víme, že to jsou akce pro přidání, zobrazení, editaci a odstraněnín článku. O výsledku se můžeme přesvědčit příkazem php artisan route:list:

+--------+-----------+------------------------+-----------------+------------------------------------------------+------------+
| Domain | Method    | URI                    | Name            | Action                                         | Middleware |
+--------+-----------+------------------------+-----------------+------------------------------------------------+------------+
|        | GET|HEAD  | api/user               |                 | Closure                                        | api        |
|        |           |                        |                 |                                                | auth:api   |
|        | GET|HEAD  | article                | article.index   | App\Http\Controllers\[email protected]   | web        |
|        | POST      | article                | article.store   | App\Http\Controllers\[email protected]   | web        |
|        | GET|HEAD  | article/create         | article.create  | App\Http\Controllers\[email protected]  | web        |
|        | GET|HEAD  | article/{article}      | article.show    | App\Http\Controllers\[email protected]    | web        |
|        | PUT|PATCH | article/{article}      | article.update  | App\Http\Controllers\[email protected]  | web        |
|        | DELETE    | article/{article}      | article.destroy | App\Http\Controllers\[email protected] | web        |
|        | GET|HEAD  | article/{article}/edit | article.edit    | App\Http\Controllers\[email protected]    | web        |
+--------+-----------+------------------------+-----------------+------------------------------------------------+------------+

Tabulka výše obsahuje kromě akcí s články i API akci, která je definovaná v souboru routes/api.php. Pro nás se momentálně jedná o nepodstatnou routu, proto ji budeme ignorovat.

Tabulka rout nám popisuje tyto vlastnosti:

  • Domain - Pro kterou doménu je daná routa určená. Pokud je hodnota prázdná, platí výchozí doména.
  • Method - HTTP metoda akce. Jelikož HTML formuláře nepodporují metody PUT, PATCH ani DELETE, budeme je muset trochu modifikovat. To si ale ukážeme v další lekci.
  • URI - URI akce (v našem případě část v URL adrese za doménou).
  • Name - Název akce, který se používá v kódu pro vytvoření odkazu přes helper funkci route() (například route('article.index') vygeneruje http://localhost:8000/article).
  • Action - Metoda kontroleru zpracovávající danou akci.
  • Middleware - Výpis middlewarů, přes které požadavek projde.

Také si všimněte, že v akcích, jako je například zobrazení, je v URI definovaný parametr {article}. Pokud používáme stejný název parametru jako proměnné v metodě kontroleru, můžeme následně získat instanci článku pouze díky dependency injection, viz dále.

Předpřipravený článek

Do naší tabulky článků si ještě doplníme úvodní článek, abychom měli s čím pracovat, než cokoliv vytvoříme.

Podle oficiálního postupu bychom si měli připravit tzv. seedery. Toho vás chci ale prozatím ušetřit. Místo toho si ukážeme nový Artisan příkaz - tinker. Jedná se o PHP konzoli, přes kterou můžeme provést jakoukoliv operaci a to i s třídami frameworku. Do konzole poté vložíme následující kód, skrz který vytvoříme nový článek:

$article = new App\Article();
$article->title = 'Úvod';
$article->url = 'uvod';
$article->description = 'Úvodní článek na webu v Laravel frameworku.';
$article->content = '<p>Vítejte na našem webu!</p><p>Tento web je postaven na <strong>jednoduchém redakčním systému v Laravel frameworku</strong>. Toto je úvodní článek, načtený z databáze.</p>';
$article->save();
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Nakonec nám metoda save() vrátí boolean hodnotu úspěchu:

Použití PHP konzole v Laravel frameworku pro vytvoření článku

Kontroler

Nyní se přesuneme ke kontroleru. Tam pouze upravíme akci show(), aby nám vracela pohled spolu s daty článku:

/**
 * Načti článek a předej jeho data do šablony.
 *
 * @param  Article $article
 * @return Application|Factory|View
 */
public function show(Article $article)
{
    return view('article.show', ['article' => $article]);
}

Nezapomeneme přidat i importy pro třídy zmíněné v dokumentaci:

use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\View\View;

Pohledy

Abychom si článek mohli zobrazit, budeme k tomu potřebovat pohled. Předtím, než však začneme nějaký vytvářet, si prosím odstraňte vygenerovaný pohled resources/views/welcome.blade.php, my ho totiž potřebovat nebudeme :)

Šablona webu

Začneme úpravou celkového vzhledu naší aplikace. Ten bude zajišťovat hlavní pohled base.blade.php:

<!DOCTYPE html>
<html lang="cs-CZ">
    <head>
        <meta charset="utf-8" />
        <meta name="csrf-token" content="{{ csrf_token() }}" />
        <meta name="description" content="@yield('description')" />
        <title>@yield('title', env('APP_NAME'))</title>

        <link href="{{ asset('css/app.css') }}" rel="stylesheet" />

        <script src="{{ asset('js/app.js') }}"></script>
    </head>
    <body>
        <div class="d-flex flex-column flex-md-row align-items-center p-3 px-md-4 mb-3 bg-white border-bottom shadow-sm">
            <h5 class="my-0 mr-md-auto font-weight-normal">{{ env('APP_NAME') }}</h5>
            <nav class="my-2 my-md-0 mr-md-3">
                <a class="p-2 text-dark" href="#">Hlavní stránka</a>
                <a class="p-2 text-dark" href="#">Seznam článků</a>
                <a class="p-2 text-dark" href="#">Kontakt</a>
            </nav>
        </div>

        <div class="container">
            @if ($errors->any())
                <div class="alert alert-danger mb-4">
                    <ul class="mb-0">
                        @foreach ($errors->all() as $error)
                            <li>{{ $error }}</li>
                        @endforeach
                    </ul>
                </div>
            @endif

            @yield('content')

            <footer class="pt-4 my-md-5 border-top">
                <p>
                    Ukázkový tutoriál pro jednoduchý redakční systém v Laravel frameworku z programátorské sociální sítě
                    <a href="http://www.itnetwork.cz" target="_blank">itnetwork.cz</a>
                </p>
            </footer>
        </div>

        @stack('scripts')
    </body>
</html>

V lekci Jednoduchý redakční systém v Laravel - Struktura projektu jsme si do projektu naimportovali CSS framework Bootstrap. Toho jsem využil při tvorbě této šablony, kdy jsem si stáhl jeden z jejich příkladů a trochu ho upravil, aby naše stránka alespoň trochu vypadala k světu :)

Na pohledu výše si také všimněte těchto Blade direktiv:

  • @yield('hodnota') - Očekává se předání jedné hodnoty z pohledu, který dědí tento pohled. Do hlavní šablony se nám tak např. předá titulek z šablony aktuální podstránky. Můžeme definovat i výchozí hodnotu, toho využíváme zrovna u titulku stránky. Hodnota bloku se přiřazuje Blade direktivami @section (popř. @endsection).
  • @stack - Jedná se o kolekci zásobník na rozdíl od @yield. To se nám hodí pro přidávání skriptů, jelikož je můžeme předávat ve více pohledech pro jednu stránku. Do zásobníku se přidávají hodnoty pomocí Blade direktiv @push (popř. @endpush)

Zobrazení článku

V pohledu pro zobrazení článku, který si vytvoříme ve složce resources/views/article s názvem show.blade.php, budeme dědit naší hlavní šablonu a následně využijeme bloků, které jsme si definovali:

@extends('base')

@section('title', $article->title)
@section('description', $article->description)

@section('content')
    <h1>{{ $article->title }}</h1>
    {!! $article->content !!}
@endsection

Jelikož framework nás chrání před XSS útokem pomocí escapování vypsaného textu, musíme pro výpis obsahu článku použít {!! !!} namísto {{ }}. Obsahuje totiž i HTML kód.

Pokud si však nyní zkusíme zobrazit náš úvodní článek přes stránku webu /article/uvod, dostaneme chybu 404 i přes to, že vše vypadá funkčně. Kde je tedy chyba?

Definování atributu pro parametr routy

Laravel ve výchozím nastavení získává data z databáze pomocí jejich ID. Pro zobrazení úvodního článku bychom museli použít adresu /article/1. Jedná se však o nechtěné chování aplikace, jelikož každý náš článek má svojí unikátní slovní URL a toho chceme využít.

Aby se aplikovala hodnota url článku v routách používající model Article (parametr {article}), budeme muset v našem modelu přepsat obsah metody getRouteKeyName(), která se dědí z třídy Model:

/**
 * Vrať název atributu, podle kterého se získává článek z parametru routy.
 *
 * @return string
 */
public function getRouteKeyName()
{
    return 'url';
}

Nyní při navštívení stránky /article/uvod uvidíme náš úvodní článek:

Zobrazení úvodního článku v PHP frameworku Laravel

Úplný základ článků máme zprovozněný.

V příští lekci, Jednoduchý redakční systém v Laravel - Tvorba článků, se podíváme na vytváření článků a zobrazení jejich seznamu v administraci.


 

Stáhnout

Staženo 62x (44.44 MB)
Aplikace je včetně zdrojových kódů v jazyce php

 

Předchozí článek
Jednoduchý redakční systém v Laravel - Migrace
Všechny články v sekci
Laravel framework pro PHP
Článek pro vás napsal Jan Lupčík
Avatar
Jak se ti líbí článek?
6 hlasů
Autor se primárně věnuje vývoji webových stránek a aplikacích v PHP (speciálně ve frameworku Laravel) a je jedním z vývojářů komunitní modifikace TruckersMP.
Aktivity (14)

 

 

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

Avatar
bhm81
Člen
Avatar
bhm81:30. března 19:18

Ahoj, měl bych takový zvláštní dotaz. Vzhledem k tomu, že přes artisan vytvořím "Article" model, "ArticleController" kontroler, tak mám i v routu/url řádku "/article/uvod", který se generuje automaticky. Ale co když bych tam chtěl mít "/clanky/uvod". Lze to nějakou funkcí přejmenovat? Nechci vytvářet třídy v češtině jako "ClankyController", to mi přijde trochu úchylný... Díky za radu...

 
Odpovědět
30. března 19:18
Avatar
Odpovídá na bhm81
Martin Kašpar:31. března 9:33

Ahoj, vyzkoušej následující úpravu routy:

Route::resource('clanek', 'ArticleController', ['names' => 'article', 'parameters' => ['clanek' => 'article']]);

Výpis originálních a upravených rout.

# artisan route:list před úpravou
GET|HEAD  | article                | article.index   | App\Http\Controllers\[email protected]
POST      | article                | article.store   | App\Http\Controllers\[email protected]
GET|HEAD  | article/create         | article.create  | App\Http\Controllers\[email protected]
GET|HEAD  | article/{article}      | article.show    | App\Http\Controllers\[email protected]
PUT|PATCH | article/{article}      | article.update  | App\Http\Controllers\[email protected]
DELETE    | article/{article}      | article.destroy | App\Http\Controllers\[email protected]
GET|HEAD  | article/{article}/edit | article.edit    | App\Http\Controllers\[email protected]

# artisan route:list po úpravě
GET|HEAD  | clanek                 | article.index   | App\Http\Controllers\[email protected]
POST      | clanek                 | article.store   | App\Http\Controllers\[email protected]
GET|HEAD  | clanek/create          | article.create  | App\Http\Controllers\[email protected]
GET|HEAD  | clanek/{article}       | article.show    | App\Http\Controllers\[email protected]
PUT|PATCH | clanek/{article}       | article.update  | App\Http\Controllers\[email protected]
DELETE    | clanek/{article}       | article.destroy | App\Http\Controllers\[email protected]
GET|HEAD  | clanek/{article}/edit  | article.edit    | App\Http\Controllers\[email protected]

Dál za nastavení rout jsem to nezkoušel, tak nemusí jít na sto procent o všechny potřebné úpravy.

 
Odpovědět
31. března 9:33
Avatar
Jan Lupčík
Super redaktor
Avatar
Odpovídá na bhm81
Jan Lupčík:31. března 18:33

Omlouvám se, ale včera už jsem se k odpovědi nedostal.
Úprava od Martin Kašpar je správná a děkuji mu za odpověď. Každopádně rád bych jeho úpravy trochu okomentoval.

Metoda resource() třídy Route přijímá tři parametry. První parametr určuje název v URI akci, název samotné routy a i pojmenování parametru. V druhém parametru specifikuješ kontroler, který má dané routy obsluhovat. Musí obsahovat všechny CRUD metody zmíněné v předchozí lekci :)
Třetí parametr přijímá pole nastavení, kde můžeš přepsat jak název routy (klíč names), tak i jméno parametru (klíč parameters). U parametru musíme převést clanek na article, jelikož clanek je vygenerovaný právě podle prvního parametru a náš kód kontroleru využívá proměnnou s názvem article - ty se musí shodovat, aby dependency injection správně fungovalo.

Odpovědět
31. března 18:33
TruckersMP vývojář
Avatar
bhm81
Člen
Avatar
bhm81:1. dubna 18:09

Díky moc za odpovědi... funguje to skvěle...

 
Odpovědět
1. dubna 18:09
Avatar
Jan Štěch
Super redaktor
Avatar
Jan Štěch:15. června 22:02

Jaký má význam umisťovat csrf token jako <meta> do <head>? Aplikuje se tak pro všechny formuláře, co se mohou na stránce vyskytovat? Fungoval by zde zkrácený zápis @csfr stejně jako kdybychom token vložili někam do <body>?

 
Odpovědět
15. června 22:02
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Jan Lupčík
Super redaktor
Avatar
Odpovídá na Jan Štěch
Jan Lupčík:16. června 10:06

CSRF token nastavený jako meta informace je užitečný pro odesílání požadavků přes JavaScript, který si ho může takto natáhnout z hlavičky stránky :)
Direktiva @csrf by pro to nefungovala, jelikož ta vygeneruje skrytý <input /> políčko, nikoliv <meta> tag.

Odpovědět
16. června 10:06
TruckersMP vývojář
Avatar
Jan Štěch
Super redaktor
Avatar
Odpovídá na Jan Lupčík
Jan Štěch:16. června 19:41

Jasný. Díky za vysvětlení.

 
Odpovědět
16. června 19:41
Avatar
Martin Šebek:16. června 21:19

Ahoj všem,
nevíte kde může být chyba? Pracuji v ubuntu, mám rozběhnutý apache2 server a téměř vše mi funguje až do chvíle, než se chci podívat někam jinam, než na stránku http://laravel-cms. Jakmile za tuto adresu, která mi aktuálně vyhazuje správně 404 error (nastylovaný laravelem), přidám třeba právě /article/uvod, tak dostanu klasickou chybu 404, kterou generuje přímo apache. Díky

 
Odpovědět
16. června 21:19
Avatar
Jan Lupčík
Super redaktor
Avatar
Odpovídá na Martin Šebek
Jan Lupčík:17. června 17:42

Zřejmě máš špatně nastavený web server. Pokud chceš stále využívat vlastní doménu na lokálním stroji, podívej se na nastavení do lekce o instalaci projektu: https://www.itnetwork.cz/…eni-projektu
Pokud se v dané problematice neorientuješ, myslím si, že není důležité se tím aktuálně podrobněji zabývat a můžeš zvolit možnost s vestavěným serverem.

Odpovědět
17. června 17:42
TruckersMP vývojář
Avatar
Odpovídá na Jan Lupčík
Martin Šebek:17. června 21:13

Ahoj,
díky moc za odpověď. Hodně mi pomohlo, že jsem se ujistil, že mám hledat problém v nastavení apache. Problém jsem vyřešil - apache nenačítal modul mod_rewrite. Proto fungoval jen index a věci umístěné v root složce. Po spuštění už to jede v pohodě.

 
Odpovědět
17. června 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 10 zpráv z 21. Zobrazit vše