Aktuálně: Postihly zákazy tvou profesi? Poptávka po ajťácích prudce roste, využij slevové akce 30% výuky zdarma!
Pouze tento týden sleva až 80 % na e-learning týkající se PHP
PHP týden

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

V minulej lekcii, Jednoduchý redakčný systém v Laravel - Migrácia , sme sa venovali migráciám a vytvorili sme si modelovú vrstvu pre články. Ako som sľúbil, dnes budeme v PHP Laravel tutoriálu pokračovať v tvorbe kontroleru a sprevádzkujeme si zobrazenie článku.

Routovanie

Začneme najskôr tým, že si definujeme ruty pre články. Otvoríme si súbor routes/web.php a odstránime predvolené route pre hlavnú stránku, pretože ju zatiaľ v našom projekte nebudeme potrebovať. Namiesto nej si definujeme, že nami vytvorený CRUD kontrolér má spracovávať požiadavky na články:

use Illuminate\Support\Facades\Route;

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

Metódou resource() sme definovali ruty pre všetky CRUD akcie kontroleru. Už vieme, že to sú akcie pre pridanie, zobrazenie, editáciu a odstraněnín článku. O výsledku sa môžeme presvedčiť príkazom php artisan route:list:

+--------+-----------+----------------------------+-----------------+------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+
| Domain | Method    | URI                        | Name            | Action                                                     | Middleware                                                                                                                         |
+--------+-----------+----------------------------+-----------------+------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+
|        | POST      | _ignition/execute-solution |                 | Facade\Ignition\Http\Controllers\ExecuteSolutionController | Facade\Ignition\Http\Middleware\IgnitionEnabled,Facade\Ignition\Http\Middleware\IgnitionConfigValueEnabled:enableRunnableSolutions |
|        | GET|HEAD  | _ignition/health-check     |                 | Facade\Ignition\Http\Controllers\HealthCheckController     | Facade\Ignition\Http\Middleware\IgnitionEnabled                                                                                    |
|        | GET|HEAD  | _ignition/scripts/{script} |                 | Facade\Ignition\Http\Controllers\ScriptController          | Facade\Ignition\Http\Middleware\IgnitionEnabled                                                                                    |
|        | POST      | _ignition/share-report     |                 | Facade\Ignition\Http\Controllers\ShareReportController     | Facade\Ignition\Http\Middleware\IgnitionEnabled,Facade\Ignition\Http\Middleware\IgnitionConfigValueEnabled:enableShareButton       |
|        | GET|HEAD  | _ignition/styles/{style}   |                 | Facade\Ignition\Http\Controllers\StyleController           | Facade\Ignition\Http\Middleware\IgnitionEnabled                                                                                    |
|        | 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                                                                                                                                |
+--------+-----------+----------------------------+-----------------+------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+

Tabuľka vyššie obsahuje okrem akcií s článkami aj API akciu, ktorá je definovaná v súbore routes/api.php, a akcie pre debugger. Pre nás sa momentálne jedná o nepodstatné ruty, preto ich budeme ignorovať.

Tabuľka rout nám opisuje tieto vlastnosti:

  • Domain - Pre ktorú doménu je daná ruta určená. Ak je hodnota prázdna, platí východiskové doména.
  • Method - HTTP metóda akcie. Keďže HTML formuláre nepodporujú metódy PUT, PATCH ani DELETE, budeme ich musieť trochu modifikovať. To si však ukážeme v ďalšej lekcii.
  • URI - URI akcie (v našom prípade časť v URL adrese za doménou).
  • Name - Názov podujatia, ktorý sa používa v kóde pre vytvorenie odkazu cez helper funkciu route() (napríklad route('article.index') vygeneruje http://localhost:8000/article).
  • Action - Metóda kontroleru spracovávajúci danú akciu.
  • Middleware - Výpis Middleware, cez ktoré požiadavka prejde.
Tiež si všimnite, že v akciách, ako je napríklad zobrazenie, je v URI definovaný parameter {article}. Ak používame rovnaký názov parametra ako premenné v metóde kontroleru, môžeme následne získať inštanciu článku iba vďaka dependency injection, viď ďalej.

Predpripravený článok

Do našej tabuľky článkov si ešte doplníme úvodný článok, aby sme mali s čím pracovať, než čokoľvek vytvoríme.

Podľa oficiálneho postupu by sme si mali pripraviť tzv. Seeder. Toho vás chcem ale zatiaľ ušetriť. Namiesto toho si ukážeme nový Artisan príkaz - tinker. Jedná sa o PHP konzolu, cez ktorú môžeme vykonať akúkoľvek operáciu a to aj s triedami frameworku. Do konzoly potom vložíme nasledujúci kód, skrz ktorý vytvoríme nový článok:

$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íjať nasledujúce firmy, ktoré možno hľadajú práve teba!

Nakoniec nám metóda save() vráti boolean hodnotu úspechu:

Použitie PHP konzola v Laravel frameworku pre vytvorenie článku

Kontrolér

Teraz sa presunieme ku kontroleru. Tam len upravíme akciu show(), aby nám vracala pohľad spolu s dátami článku:

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

Pohľady

Aby sme si článok mohli zobraziť, budeme k tomu potrebovať pohľad. Predtým, než však začneme nejaký vytvárať, si prosím odstráňte vygenerovaný pohľad resources/views/welcome.blade.php, my ho totiž potrebovať nebudeme :)

Šablóna webu

Začneme úpravou celkového vzhľadu našej aplikácie. Ten bude zabezpečovať hlavné pohľad 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 lekcii Jednoduchý redakčný systém v Laravel - Štruktúra projektu sme si do projektu importovali CSS framework Bootstrap. Toho som využil pri tvorbe tejto šablóny, kedy som si stiahol jeden z ich príkladov a trochu ho upravil, aby naše stránka aspoň trochu vyzerala k svetu :)

Na pohľadu vyššie si tiež všimnite týchto Blade direktív:

  • @yield('hodnota') - Očakáva sa odovzdanie jednej hodnoty z pohľadu, ktorý dedí tento pohľad. Do hlavnej šablóny sa nám tak napr. Odovzdá titulok z šablóny aktuálnej podstránky. Môžeme definovať aj predvolenú hodnotu, toho využívame práve pri titulku stránky. Hodnota bloku sa priraďuje Blade direktívami @section (popr. @endsection).
  • @stack - Ide o kolekciu zásobník na rozdiel od @yield. To sa nám hodí pre pridávanie skriptov, pretože ich môžeme odovzdávať vo viacerých pohľadoch pre jednu stránku. Do zásobníka sa pridávajú hodnoty pomocou Blade direktív @push (popr. @endpush)
Zobrazenie článku

V pohľadu pre zobrazenie článku, ktorý si vytvoríme v priečinku resources/views/article s názvom show.blade.php, budeme dediť našou hlavnou šablónu a následne využijeme blokov, ktoré sme si definovali:

@extends('base')

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

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

Keďže framework nás chráni pred XSS útokom pomocou uvádzacích vypísaného textu, musíme pre výpis obsahu článku použiť {!! !!} namiesto {{ }}. Obsahuje totiž aj HTML kód.

Ak si však teraz skúsime zobraziť náš úvodný článok cez stránku webu /article/uvod, dostaneme chybu 404 aj cez to, že všetko vyzerá funkčne. Kde je teda chyba?

Definovanie atribútu pre parameter ruty

Laravel v predvolenom nastavení získava dáta z databázy pomocou ich ID. Pre zobrazenie úvodného článku by sme museli použiť adresu /article/1. Jedná sa však o nechcené správanie aplikácie, pretože každý náš článok má svoju unikátnu slovné URL a toho chceme využiť.

Aby sa aplikovala hodnota url článku v routách používajúce model Article (parameter {article}), budeme musieť v našom modeli prepísať obsah metódy getRouteKeyName(), ktorá sa dedí z triedy Model:

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

Teraz pri navštívení stránky /article/uvod uvidíme náš úvodný článok:

Zobrazenie úvodného článku v PHP frameworku Laravel

Úplný základ článkov máme sprevádzkovaný. V budúcej lekcii, Jednoduchý redakčný systém v Laravel - Tvorba článkov , pôjdeme zase o niečo hlbšie. Pozrieme sa totiž na vytváranie článkov a zobrazenie ich zoznamu v administrácii.


 

Mala si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 110x (46.78 MB)
Aplikácia je vrátane zdrojových kódov v jazyku php

 

Predchádzajúci článok
Jednoduchý redakčný systém v Laravel - Migrácia
Všetky články v sekcii
Laravel framework pre PHP
Článok pre vás napísal Jan Lupčík
Avatar
Ako sa ti páči článok?
Ešte nikto nehodnotil, buď prvý!
Autor se primárně věnuje vývoji webových stránek a aplikací v PHP (framework Laravel) a je jedním z herních vývojářů komunitní modifikace TruckersMP.
Aktivity (1)

 

 

Komentáre

Avatar
Jan Lupčík
Super redaktor
Avatar
Jan Lupčík:17.6.2020 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.

Odpovedať
17.6.2020 17:42
TruckersMP vývojář
Avatar
Odpovedá na Jan Lupčík
Martin Šebek:17.6.2020 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ě.

 
Odpovedať
17.6.2020 21:13
Avatar
dehtak
Člen
Avatar
dehtak:28.9.2020 11:39

Ahoj
Kdyz zadam do routru Route::resource('ar­ticle', 'ArticleContro­ller');
a pote dam prikaz artisan route:list tak to vyhodi chybovou hlasku ze ArticleController neexistuje. Pritom ho tam mam.

 
Odpovedať
28.9.2020 11:39
Avatar
dehtak
Člen
Avatar
dehtak:3.10.2020 0:33

tak nic no, premejslel jsem ze si koupim ten kurz ale presvedcili jste me abych to nedelal.

 
Odpovedať
3.10.2020 0:33
Avatar
Jan Lupčík
Super redaktor
Avatar
Odpovedá na dehtak
Jan Lupčík:4.10.2020 14:09

Ahoj, seriál ještě nebyl aktualizovaný na nejnovější verzi frameworku Laravel. Na začátku seriálu v první lekci je zmíněná verze, která byla zde použitá.
U verze 8.x se však routování řeší jinak. Jedním z řešení je dosazení odkazu na třídu a jméno metody akce v poli. U resource kontroleru stačí pouze předat odkaz na kontroler následujícím způsobem:

use App\Http\Controllers\ArticleController;

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

Druhou možností je odkomentování proměnné $namespace ve třídě RouteServiceProvider. Aktuálně totiž není nastaven žádný namespace, a proto framework hledá kontrolery v kořenové složce projektu.

Též bych se chtěl omluvit za pozdější odpověď, avšak poslední týden jsem toho měl hodně a nestíhal jsem tak na nic reagovat. Na aktualizaci seriálu bych se rád podíval v následujících dvou týdnech.

Odpovedať
4.10.2020 14:09
TruckersMP vývojář
Tento výukový obsah pomáhajú rozvíjať nasledujúce firmy, ktoré možno hľadajú práve teba!
Avatar
dehtak
Člen
Avatar
Odpovedá na Jan Lupčík
dehtak:7.10.2020 9:35

to uz je stejne jedno pouzivam nette

 
Odpovedať
7.10.2020 9:35
Avatar
Matúš Jumperis:25. marca 11:44

Nazdar, prosim Vas viete mi poradit preco mi to pod nginx nefunguje a podn apache ano? Pri nginx mi funguje len homepage pri apache v pohode slape vsteko. Na lokal server pouzivam svoje NASko Synology. Dakujem za kazdu radu.

P.S.: nepodarilo sa mi nainstalovat ten boostrap :-D ale tomu sa este povenujem

 
Odpovedať
25. marca 11:44
Avatar
Matúš Jumperis:7. apríla 16:06

Ahoj, mam teraz uplne iny problem. Tinker:
>>> $inOrder = new App\InOrder();
PHP Error: Class 'App\InOrder' not found in Psy Shell code on line 1

vobc tomu nechapem. Skusal aj google ale nic mi nepomaha co tam pisu

 
Odpovedať
7. apríla 16:06
Avatar
Jan Lupčík
Super redaktor
Avatar
Odpovedá na Matúš Jumperis
Jan Lupčík:7. apríla 22:44

Ahoj, ujisti se, že existuje model InOrder. Pokud ano, ve verzi 8.0 a výš jsou modely umístěné ve složce app/Models/. Tudíž celý příkaz by měl vypadat následovně:

$inOrder = new App\Models\InOrder();
Odpovedať
7. apríla 22:44
TruckersMP vývojář
Avatar
Odpovedá na Jan Lupčík
Matúš Jumperis:9. apríla 10:13

ano dik uz mi to funguje - cital som aj docs :D

 
Odpovedať
9. apríla 10:13
Robíme čo je v našich silách, aby bola tunajšia diskusia čo najkvalitnejšia. Preto do nej tiež môžu prispievať len registrovaní členovia. Pre zapojenie sa do diskusie sa zaloguj. Ak ešte nemáš účet, zaregistruj sa, je to zadarmo.

Zatiaľ nikto nevložil komentár - buď prvý!