IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

9. diel - Jednoduchý redakčný systém v Laravel - Správa článkov

V minulej lekcii, Jednoduchý redakčný systém v Laravel - Tvorba článkov , sme začali s tvorbou administrácie pre jednoduchý redakčný systém v Laravel frameworku. Vytvorili sme si zoznam článkov a editor pre ich tvorbu. V dnešnej tutoriále dokončíme administráciu pridaním editácia článkov spolu s ich odstraňovaním a povieme si niečo o triedach HTTP požiadaviek.

HTTP požiadavky

Predtým než sa vrhneme na vytváranie nových častí aplikácie, sa spätne pozrieme na našej metódu store() v kontroleru ArticleController.php, ktorú sme definovali v minulej lekcii. Ako už názov napovedá, táto metóda by mala slúžiť pre vkladanie nového záznamu (v našom prípade článku) do databázy. Okrem iného ale obsahuje tiež validáciu prijatých dát, čo v prípade väčších formulárov nemusí byť práve praktické. Preto si predstavíme tzv. Request triedy.

Request triedy

Request triedy kontrolujú, či je používateľ oprávnený pre odoslanie danej požiadavky, a zvalidujú odoslané dáta. Môžeme tak presunúť sadu pravidiel daného HTTP požiadavky práve do nich a metóda kontroleru bude potom obsahovať len logiku akcie. Poďme si teraz takú triedu vytvoriť.

Pre akciu store() si vygenerujeme triedu StoreRequest pomocou Artisan príkazu make:request, ktorý nepotrebuje žiadne špeciálne možnosti:

php artisan make:request Article/StoreRequest

Keďže tried požiadaviek môžeme mať pre jeden kontrolér viac, je dobrým zvykom vytvárať pre každý kontrolér vlastné zložku.

Vytvorila sa nám automaticky nový priečinok app/Http/Requests/ následne s nami definovanou podpriečinok Article/. V nej nájdeme vygenerovaný súbor StoreRequest.php, ktorého obsah je nasledovné:

<?php

namespace App\Http\Requests\Article;

use Illuminate\Foundation\Http\FormRequest;

class StoreRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return false;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            //
        ];
    }
}

Novo vygenerovaná trieda StoreRequest dedič triedu frameworku FormRequest obsahuje iba tieto dve metódy:

  • authorize() - Určuje, či je používateľ oprávnený pre odoslania požiadavky. Ide o jedno z miest, kam môžeme toto overenie umiestniť. Ďalším z nich môže byť napríklad middleware, to si však ukážeme až v ďalších lekciách.
  • rules() - Vracia pole s nastavenými overovacími pravidlami.

Keďže sa oprávneniami (a užívateľmi) zatiaľ nezaoberáme, môžeme metódu authorize() kompletne odstrániť. Ak totiž nie je definovaná, automaticky sa overenie považuje za úspešné. Čo už nás ale zaujíma viac, je práve metóda rules(), ktorú naplníme pravidlami z metódy store() nášho kontroleru. Bude teda vyzerať takto:

/**
 * Vrať validační pravidla pro formulář, který má na starosti tvorbu článků.
 *
 * @return array
 */
public function rules()
{
    return [
        'title' => ['required', 'min:3', 'max:80'],
        'url' => ['required', 'min:3', 'max:80', 'unique:articles,url'],
        'description' => ['required', 'min:25', 'max:255'],
        'content' => ['required', 'min:50'],
    ];
}

Následne môžeme validáciu z metódy store() kompletne odstrániť. Upravíme však typ objektu premennej $request na našej Request triedu miesto tej obyčajnej, aby sa následne aplikovala aj definované pravidlá:

/**
 * Zvaliduj odeslaná data přes formulář a vytvoř nový článek.
 *
 * @param  StoreRequest $request
 * @return Response
 */
public function store(StoreRequest $request)
{
    Article::create($request->all());

    return redirect()->route('article.index');
}

Nezabudneme samozrejme importovať našej novú triedu:

use App\Http\Requests\Article\StoreRequest;

Z metódy, ktorá na začiatku mala 25 riadkov vrátane dokumentácie, sme následne vytvorili metódu s iba 12 riadkami a to sme zachovali úplne rovnakú funkčnosť! Len si teraz skúste vytvoriť nejaký článok a ignorovať niektoré z validačných pravidiel. Trieda HTTP požiadavky vás nepustí ďalej :)

Editácia článkov

Poďme sa teraz presunúť k editácii článku.

Akcie edit () a update ()

Pohľad s formulárom pre jeho úpravu budeme vracať v metóde edit():

/**
 * Zobraz formulář pro editaci článku a předej danému pohledu načtený článek.
 *
 * @param  Article $article
 * @return Response
 */
public function edit(Article $article)
{
    return view('article.edit', ['article' => $article]);
}

Samotná úprava záznamu bude prebiehať v metóde update():

/**
 * Zvaliduj odeslaná data přes formulář a uprav načtený článek.
 *
 * @param  UpdateRequest $request
 * @param  Article $article
 * @return Response
 */
public function update(UpdateRequest $request, Article $article)
{
    $article->update($request->all());

    return redirect()->route('article.index');
}

Rovnako ako u akcie store(), aj tu odovzdáme Eloquent metóde iba polia dát z formulára, v tomto prípade metóde update().

UpdateRequest

Pre validáciu dát opäť používame vlastné Request triedu s názvom UpdateRequest, ktorú si teraz vygenerujeme v priečinku app/Http/Requests/Article/ pomocou už spomínaného Artisan príkazu:

php artisan make:request Article/UpdateRequest

Túto vygenerovanú triedu si ihneď upravíme. Odstránime metódu authorize() a definujeme si validačné pravidlá v metóde rules():

<?php

namespace App\Http\Requests\Article;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class UpdateRequest extends FormRequest
{
    /**
     * Vrať validační pravidla pro formulář, který má na starosti editaci článků.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'title' => ['required', 'min:3', 'max:80'],
            'url' => [
                'required',
                'min:3',
                'max:80',
                Rule::unique('articles', 'url')->ignore($this->route('article')->id),
            ],
            'description' => ['required', 'min:25', 'max:255'],
            'content' => ['required', 'min:50'],
        ];
    }
}

Pre editáciu článku sa validačné pravidlá stala trochu zložitejšími. Pre validačný pravidlo unique musíme definovať výnimku aktuálneho záznamu. Keby sme ju totiž nedefinovali a chceli pozmeniť článok bez modifikácie jeho URL, validácia by nám následne vyhodila chybu, že v databáze už existuje článok s danou URL adresou, aj keď sa jedná o práve editovaný článok.

Túto výnimku nastavujeme skrz metódu ignore() Builderu Unique, ktorá prijíma ID záznamu. Tiež si všimnite ďalšie výhody parametrov fungujúcich cez dependency injection (tzv. Route model binding). Inštanciu modelu článku môžeme ľahko získať pomocou metódy route() triedy frameworku FormRequest, kedy odovzdáme názov parametra definovaného v routovacím súbore a nemusíme tento záznam zložito vyberať z databázy iba cez odovzdaný identifikátor (v našom prípade URL článku).

Nakoniec pridáme do nášho kontroleru ArticleController import tejto novej triedy:

use App\Http\Requests\Article\UpdateRequest;

Pohľad

Teraz si vytvoríme pohľad s názvom edit.blade.php v priečinku resources/views/article/, ktorý je takmer totožný s pohľadom create.blade.php:

@extends('base')

@section('title', 'Editace článku ' . $article->title)
@section('description', 'Editor pro editaci článků.')

@section('content')
    <h1>Editace článku {{ $article->title }}</h1>

    <form action="{{ route('article.update', ['article' => $article]) }}" method="POST">
        @csrf
        @method('PUT')

        <div class="form-group">
            <label for="title">Nadpis</label>
            <input type="text" name="title" id="title" class="form-control" value="{{ old('title') ?: $article->title }}" required minlength="3" maxlength="80" />
        </div>

        <div class="form-group">
            <label for="url">URL</label>
            <input type="text" name="url" id="url" class="form-control" value="{{ old('url') ?: $article->url }}" required minlength="3" maxlength="80" />
        </div>

        <div class="form-group">
            <label for="description">Popisek článku</label>
            <textarea name="description" id="description" rows="4" class="form-control" required minlength="25" maxlength="255">{{ old('description') ?: $article->description }}</textarea>
        </div>

        <div class="form-group">
            <label for="content">Obsah článku</label>
            <textarea name="content" id="content" class="form-control" rows="8">{{ old('content') ?: $article->content }}</textarea>
        </div>

        <button type="submit" class="btn btn-primary">Uložit článek</button>
    </form>
@endsection

@push('scripts')
    <script type="text/javascript" src="{{ asset('//cdn.tinymce.com/4/tinymce.min.js') }}"></script>
    <script type="text/javascript">
        tinymce.init({
            selector: '#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>
@endpush

Keďže HTTP akcie store() je typu PUT, musíme vo formulári opäť použiť Blade direktívu @method.

Ak teraz vyskúšame upraviť niektorý z existujúcich článkov, všetko prebehne úplne v poriadku. Za pozornosť ešte stojí dátum poslednej zmeny v zozname článkov, ktorý sa automaticky aktualizuje pri akejkoľvek zmene daného záznamu. Len si to sami vyskúšajte :)

Odstraňovanie článkov

Posledná časť administrácie, ktorá nám chýba, je odstraňovanie článkov. Keďže formulár pre túto akciu už máme vytvorený v zozname článkov a venovali sme sa mu minulú lekciu, stačí nám teraz iba upraviť akciu destroy() v našom kontroleru:

/**
 * Odstraň článek z databáze.
 *
 * @param  Article $article
 * @return Response
 */
public function destroy(Article $article)
{
    try {
        $article->delete();
    } catch (\Exception $exception) {
        return redirect()->back()->withErrors(['Při procesu odstranění článku došlo k chybě.']);
    }

    return redirect()->route('article.index');
}

Na odstránenie záznamu používame Eloquent metódu delete(), v ktorej však môže dôjsť k výnimke. Tú musíme ošetriť, aby sa užívateľovi nezobrazila stránka s chybou 500. presmeruje ho teda späť (na to používame metódu back() builder funkcia redirect()) a dáme mu vedieť, že proces odstránenia sa nepodaril.

Týmto sme dokončili vzhľadnú a plne fungujúce administráciu. Ak sa vám niečo nepodarilo, môžete si stiahnuť projekt z priloženého archívu nižšie. V opačnom prípade výsledok nášho snaženia môžeme zhrnúť takto obrázkom:

Zoznam článkov v administrácii v Laravel redakčnom systéme - Laravel framework pre PHP

V budúcej lekcii, Kvíz - Štruktúra projektu, migrácia a šablóny v Laravel , sa zameriame viac na front-end časť našej aplikácie. Pozrieme sa totiž na možnosti kompilácie súborov, ako sú JavaScript, SCSS, LESS a ďalšie.

V nasledujúcom kvíze, Kvíz - Štruktúra projektu, migrácia a šablóny v Laravel, si vyskúšame nadobudnuté skúsenosti z predchádzajúcich lekcií.


 

Mal 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é 177x (46.79 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 - Tvorba článkov
Všetky články v sekcii
Laravel framework pre PHP
Preskočiť článok
(neodporúčame)
Kvíz - Štruktúra projektu, migrácia a šablóny v Laravel
Článok pre vás napísal Jan Lupčík
Avatar
Užívateľské hodnotenie:
1 hlasov
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