Python týden Geek tričko zdarma
Tričko zdarma! Stačí před dobitím bodů použít kód TRIKO15. Více informací zde
Pouze tento sleva až 80% na kurzy Python

Lekce 9 - Jednoduchý redakční systém v Laravel - Správa článků

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 Laravel - Tvorba článků, jsme začali s tvorbou administrace pro jednoduchý redakční systém v Laravel frameworku. Vytvořili jsme si seznam článků a editor pro jejich tvorbu. V dnešní tutoriálu dokončíme administraci přidáním editace článků spolu s jejich odstraňováním a povíme si něco o třídách HTTP požadavků.

HTTP požadavky

Předtím než se vrhneme na vytváření nových částí aplikace, se zpětně podíváme na naší metodu store() v kontroleru ArticleController.php, kterou jsme definovali v minulé lekci. Jak už název napovídá, tato metoda by měla sloužit pro vkládání nového záznamu (v našem případě článku) do databáze. Mimo jiné ale obsahuje také validaci přijatých dat, což v případě větších formulářů nemusí být zrovna praktické. Proto si představíme tzv. Request třídy.

Request třídy

Request třídy kontrolují, zda-li je uživatel oprávněný pro odeslání daného požadavku, a validují odeslaná data. Můžeme tak přesunout sadu pravidel daného HTTP požadavku právě do nich a metoda kontroleru bude poté obsahovat pouze logiku akce. Pojďme si nyní takovou třídu vytvořit.

Pro akci store() si vygenerujeme třídu StoreRequest pomocí Artisan příkazu make:request, který nepotřebuje žádné speciální možnosti:

php artisan make:request Article/StoreRequest

Jelikož tříd požadavků můžeme mít pro jeden kontroler více, je dobrým zvykem vytvářet pro každý kontroler vlastní složku.

Vytvořila se nám automaticky nová složka app/Http/Requests/ následně s námi definovanou podsložkou Article/. V ní najdeme vygenerovaný soubor StoreRequest.php, jehož obsah je následující:

<?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 [
            //
        ];
    }
}

Nově vygenerovaná třída StoreRequest dědící třídu frameworku FormRequest obsahuje pouze tyto dvě metody:

  • authorize() - Určuje, zda-li je uživatel oprávněný pro odeslání požadavku. Jedná se o jedno z míst, kam můžeme toto ověření umístit. Dalším z nich může být například middleware, to si však ukážeme až v dalších lekcích.
  • rules() - Vrací pole s nastavenými validačními pravidly.

Jelikož se oprávněními (a uživateli) zatím nezabýváme, můžeme metodu authorize() kompletně odstranit. Pokud totiž není definovaná, automaticky se toto ověření považuje za úspěšné. Co už nás ale zajímá více, je právě metoda rules(), kterou naplníme pravidly z metody store() našeho kontroleru. Bude tedy vypadat 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ásledně můžeme validaci z metody store() kompletně odstranit. Upravíme však typ objektu proměnné $request na naší Request třídu místo té obecné, aby se následně aplikovala i definovaná pravidla:

/**
 * 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');
}

Z metody, která na začátku měla 25 řádků včetně dokumentace, jsme následně vytvořili metodu s pouhými 12 řádky a to jsme zachovali naprosto stejnou funkčnost! Jen si teď zkuste vytvořit nějaký článek a ignorovat některé z validačních pravidel. Třída HTTP požadavku vás nepustí dále :)

Editace článků

Pojďme se nyní přesunout k editaci článku.

Akce edit() a update()

Pohled s formulářem pro jeho úpravu budeme vracet v metodě 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 probíhat v metodě 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');
}

Stejně jako u akce store(), i zde předáme Eloquent metodě pouze pole dat z formuláře, v tomto případě metodě update().

UpdateRequest

Pro validaci dat opět používáme vlastní Request třídu s názvem UpdateRequest, kterou si nyní vygenerujeme ve složce app/Http/Requests/Article/ pomocí již zmíněného Artisan příkazu:

php artisan make:request Article/UpdateRequest

Tuto vygenerovanou třídu si ihned upravíme. Odstraníme metodu authorize() a definujeme si validační pravidla v metodě 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'],
        ];
    }
}

Pro editaci článku se validační pravidla stala trochu složitějšími. Pro validační pravidlo unique musíme definovat výjimku aktuálního záznamu. Kdybychom ji totiž nedefinovali a chtěli pozměnit článek bez modifikace jeho URL, validace by nám následně vyhodila chybu, že v databázi již existuje článek s danou URL adresou, i když se jedná o právě editovaný článek.

Tuto výjimku nastavujeme skrz metodu ignore() builderu Unique, která přijímá ID záznamu. Také si povšimněte další výhody parametrů fungujících přes dependency injection. Instanci modelu článku můžeme lehce získat pomocí metody route() třídy frameworku FormRequest, kdy předáme název parametru definovaného v routovacím souboru, a nemusíme tento záznam složitě vybírat z databáze pouze přes předaný identifikátor (v našem případě URL článku).

Pohled

Nyní si vytvoříme pohled s názvem edit.blade.php ve složce resources/views/article/, který je téměř totožný s pohledem 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

Jelikož HTTP akce store() je typu PUT, musíme ve formuláři opět použít Blade direktivu @method.

Pokud nyní vyzkoušíme upravit některý z existujících článků, vše proběhne naprosto v pořádku. Za pozornost ještě stojí datum poslední změny v seznamu článků, jenž se automaticky aktualizuje při jakékoliv změně daného záznamu. Jen si to sami vyzkoušejte :)

Odstraňování článků

Poslední část administrace, která nám chybí, je odstraňování článků. Jelikož formulář pro tuto akci už máme vytvořený v seznamu článků a věnovali jsme se mu minulou lekci, stačí nám teď pouze upravit akci destroy() v našem 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');
}

K odstranění záznamu používáme Eloquent metodu delete(), ve které však může dojít k výjimce. Tu musíme ošetřit, aby se uživateli nezobrazila stránka s chybou 500. Přesměrujeme ho tedy zpátky (na to používáme metodu back() builder funkce redirect()) a dáme mu vědět, že proces odstranění se nepodařil.

Tímto jsme dokončili vzhlednou a plně fungující administraci. Pokud se vám něco nepodařilo, můžete si stáhnout projekt z přiloženého archivu níže. V opačném případě výsledek našeho snažení můžeme shrnout tímto obrázkem:

Seznam článků v administraci v Laravel redakčním systému

V příští lekci, Jednoduchý redakční systém v Laravel - Laravel Mix, se zaměříme více na front-end část naší aplikace. Podíváme se totiž na možnosti kompilace souborů, jako jsou JavaScript, SCSS, LESS a další.


 

Stáhnout

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

 

 

Článek pro vás napsal Jan Lupčík
Avatar
Jak se ti líbí článek?
1 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ího módu TruckersMP.
Předchozí článek
Jednoduchý redakční systém v Laravel - Tvorba článků
Všechny články v sekci
Laravel framework pro PHP
Miniatura
Následující článek
Jednoduchý redakční systém v Laravel - Laravel Mix
Aktivity (4)

 

 

Komentáře

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.

Zatím nikdo nevložil komentář - buď první!