Lekce 11 - Jednoduchý redakční systém v Laravel - Práce s datem
V minulé lekci, Jednoduchý redakční systém v Laravel - Laravel Mix, jsme se věnovali zejména front-end části
našeho projektu. Přidali jsme si také Font Awesome 
Tentokrát si vysvětlíme práci s datem a následně se přesuneme na vyvíjení back-endu. Vytvoříme si totiž hlavní stránku.
Práce s datem
Určitě jste si už všimli, že data v naší aplikaci se vypisují ve
výchozí podobě z databáze a to ve formátu Y-m-d H:i:s. Jedná
se však o něco, co opravdu mít nechceme, jelikož to není zrovna intuitivní
pro uživatele. Navíc se data ukládají v UTC, i když je celá naše aplikace
v češtině (až na výjimky, tj. chybové hlášky knihoven či frameworku a
URL adresy). Časové pásmo by tedy též mělo být nejlépe
lokalizované.
V čistém PHP bychom vždy museli volat funkci date() a sami
nastavovat formát času. V lepším případě bychom na to použili knihovnu.
O to se však už postaral někdo za nás, jelikož Laravel ve výchozím
nastavení používá knihovnu Carbon. Tato knihovna obsahuje
mnoho užitečných metod a i překlady pro nespočet jazyků. Pokud vás
zajímá více, zavítejte na oficiální
stránky knihovny Carbon.
Nastavení lokalizace aplikace
Carbon si získává hodnoty pro nastavení z konfiguračního souboru
aplikace, který je, jak již zřejmě tušíte, ve složce
config/, přesněji v souboru app.php. Nás v tomto
případě zajímají tyto hodnoty:
timezone- Definuje časové pásmo pro naší aplikaci. Výchozí hodnota jeUTC. Pro střední Evropu bychom klidně mohli použítCET(Central European Time), zde však bohužel nastává problém s letním časem. Proto využijeme možnosti definovat kontinent s městem, v našem případěEurope/Prague, což vyřeší tento problém za nás.locale- Zkratka pro jazyk, který má naše aplikace používat. Výchozí hodnota jeen. My si však nastavímecs, čímž změníme nejen konfiguraci jazyka pro samotný framework, ale i pro danou knihovnu. Pokud nelze najít frázi pro daný jazyk, použije se výchozí. Záložní jazyk je definovaný konfigurační hodnotoufallback_locale. Tato hodnota je jako výchozí nastavená na angličtinu (en).
Změny v souboru vypadají takto:
/* |-------------------------------------------------------------------------- | Application Timezone |-------------------------------------------------------------------------- | | Here you may specify the default timezone for your application, which | will be used by the PHP date and date-time functions. We have gone | ahead and set this to a sensible default for you out of the box. | */ 'timezone' => 'Europe/Prague', /* |-------------------------------------------------------------------------- | Application Locale Configuration |-------------------------------------------------------------------------- | | The application locale determines the default locale that will be used | by the translation service provider. You are free to set this value | to any of the locales which will be supported by the application. | */ 'locale' => 'cs',
Nyní se již změny aplikují na naší aplikaci. Pokud si totiž zkusíme editovat článek, uvidíme, že datum poslední změny sedí i s lokálním časem. Co ale zatím nesedí, je výpis data, jelikož stále využívá výchozí formát. Pojďme to napravit.
Pokud se tyto změny neprojevily na vaší aplikaci, spusťte
příkaz php artisan config:cache v kořenové složce projektu.
Konfigurační hodnoty se totiž ukládají do mezipaměti a pomocí tohoto
příkazu se naplní novými hodnotami.
Výpis dat v pohledech
Začneme nejdříve pohledem pro článek, který najdeme ve složce
resources/views/article/ s názvem show.blade.php. Tam
vypisujeme pouze jedno datum a to poslední změnu daného záznamu v patičce
článku. Vytvoříme si tedy nový objekt třídy knihovny Carbon
a následně vypíšeme časový rozdíl oproti poslední změně pomocí
lokalizované metody diffForHumans():
@php
$updatedAt = new Carbon\Carbon($article->updated_at);
@endphp
<footer>
<p class="small text-secondary border-top pt-2 mt-4">
<i class="fa fa-calendar"></i> {{ $updatedAt->diffForHumans() }}
</p>
</footer>
Mimo klasické PHP tagy lze použít Blade direktivu
@php ... @endphp. Není mezi nimi žádný rozdíl, pouze (a snad
mi tuto připomínku ostatní vývojáři odpustí) se jedná o zkrášlení
kódu daného pohledu.
Pokud si nyní zobrazíme nějaký článek, uvidíme v patičce článku výstup podobný tomuto:

Naše aplikace opět vypadá trochu profesionálněji. Bohužel naše řešení už na tom není tak dobře. Daný postup je samozřejmě bezchybný a funguje přesně tak, jak bychom si přáli. Představte si však, že byste na jedné stránce měli například 10 různých dat a pro všechna tato data byste museli vždy vytvořit nový objekt třídy knihovny Carbon. To by bylo poněkud zdlouhavé a zároveň by se kód stal nepřehledným.
Data záznamu jako instance knihovny Carbon
Jak jste si již určitě všimli v předchozích lekcích, vždy se dá vše
zjednodušit. To samé platí pro data záznamů, jež jsou v instanci modelu
vždy reprezentovaná jako objekt třídy Carbon dědící PHP
třídu DateTime. My se tedy vytvářením nového objektu
zatěžovat nemusíme a ihned můžeme přistupovat k metodám této
knihovny.
Další datumy, které mají fungovat na stejném principu v
daném modelu, se definují v proměnné $dates.
Atributy created_at a updated_at už jsou automaticky
zahrnuté. Pokud byste tedy chtěli definovat další data, je zbytečné je
znovu specifikovat.
Část pohledu s patičkou si tedy můžeme upravit do následující podoby:
<footer> <p class="small text-secondary border-top pt-2 mt-4"> <i class="fa fa-calendar"></i> {{ $article->updated_at->diffForHumans() }} </p> </footer>
Lokalizované datum
Nejspíše se shodneme na tom, že v článku by se uživateli mělo
zobrazovat přesné datum. Na to můžeme použít jednu z mnoha dostupných
metod a to isoFormat(), jelikož jedna z výhod je lokalizovaný
výstup (což neplatí například pro metodu format()):
<footer> <p class="small text-secondary border-top pt-2 mt-4"> <i class="fa fa-calendar"></i> {{ $article->updated_at->isoFormat('LLL') }} </p> </footer>
Výstup může vypadat podobně tomuto:

Více možností pro lokalizovaný výstup lze nalézt v oficiální dokumentaci knihovny Carbon.
Následně si také upravíme zobrazení dat v administraci článků,
abychom tyto výstupy měli sjednocené. Otevřeme si tedy pohled
resources/views/article/index.blade.php a upravíme následující
část tabulky:
<td>{{ $article->description }}</td> <td>{{ $article->created_at->isoFormat('LLL') }}</td> <td>{{ $article->updated_at->isoFormat('LLL') }}</td> <td>
Hlavní stránka
Zlepšování naší aplikace zakončíme vytvořením hlavní stránky (homepage) pro náš web. Nám zatím postačí, když bude obsahovat pouze výpis nejnovějších článků.
Začneme nejdříve od kontroleru.
Kontroler o jediné akci
Jak jsme si již řekli, kontroler pro zobrazení hlavní stránky bude
definovat pouze jednu akci. Pozastavíme se však u názvu metody pro danou akci
kontroleru. Jak bychom ji totiž měli pojmenovat? Názvy jako
show() nebo index() se moc nehodí, jelikož se
nejedná o CRUD kontroler pracující s jednou instancí modelu (na hlavní
stránce nemusíme zobrazovat pouze výpis článků a navíc již jeden CRUD
kontroler pro daný model máme). Možná vás ještě napadne něco jako
getHome(), ani to však není ten nejlepší přístup.
Pro takovéto případy Laravel definuje tzv. kontrolery jediné
akce (Single
Action Controllers). Tyto kontrolery se vyznačují tím, že definují
pouze jedinou metodu __invoke(), která může přijímat parametry
stejně jako jakákoliv jiná akce.
Pojďme si nyní takový kontroler vytvořit přes Artisan příkaz
make:controller. Předtím se však podíváme na jeho
možnosti:
php artisan help make:controller

Možnost --model[=MODEL] již známe z předchozích lekcí.
Nás však tentokrát bude zajímat možnost --invokable, která
vytvoří kontroler jediné akce. Ten si pojmenujeme jako
WelcomeController:
php artisan make:controller --invokable WelcomeController
Nově vygenerovaný kontroler najdeme ve složce s kontrolery
app/Http/Controllers/ a obsahuje pouze zmíněnou metodu
__invoke():
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Http\Response; class WelcomeController extends Controller { /** * Handle the incoming request. * * @param Request $request * @return Response */ public function __invoke(Request $request) { // } }
My si přes tuto metodu zobrazíme hlavní stránku. Bude nám tedy stačit,
aby vracela pohled, kterému předáme kolekci nejnovějších článků pomocí
Eloquent metody latest():
/** * Zobraz hlavní stránku webu. * * @param Request $request * @return View */ public function __invoke(Request $request): View { return view('welcome', ['articles' => Article::latest()->get()]); }
Nesmíme zapomenout importovat náš model a třídy zmíněné v dokumentaci:
use App\Models\Article; use Illuminate\Contracts\View\View;
Routování
Routování kontrolerů jediné akce je trochu rozdílné - nedefinujeme
totiž metodu daného kontroleru, ale pouze jeho název. Pro zobrazení hlavní
stránky využívající tento kontroler si musíme do routovacího souboru
routes/web.php přidat následující volání metody
get() routovací třídy Route:
Route::get('', WelcomeController::class);
Opět musíme přidat import třídy kontroleru:
use App\Http\Controllers\WelcomeController;
Jak si můžete povšimnout, jako URI akci definujeme pouze prázdný
řetězec. Tím dosáhneme toho, že při zobrazení webu bez jakýchkoliv
jiných parametrů v URL adrese se vykoná metoda __invoke()
kontroleru pro hlavní stránku WelcomeController.
Nesmíme také zapomenout odkázat na hlavní stránku v menu naší hlavní
šablony resources/views/base.blade.php. Na to použijeme helper
funkci url():
<nav class="my-2 my-md-0 mr-md-3"> <a class="p-2 text-dark" href="{{ url('') }}">Hlavní stránka</a> <a class="p-2 text-dark" href="{{ route('article.index') }}">Seznam článků</a> <a class="p-2 text-dark" href="#">Kontakt</a> </nav>
Pohled
Hlavní stránku zakončíme vytvořením pohledu s názvem
welcome.blade.php ve složce s pohledy
resources/views/. Momentálně nebude mít na starosti nic jiného
než pouhé vypsání všech článků z naší databáze, které jsme předali
v metodě kontroleru akce:
@extends('base')
@section('title', 'Jednoduchý redakční systém v Laravel')
@section('description', 'Ukázkový tutoriál pro jednoduchý redakční systém v Laravel frameworku z programátorské sociální sítě itnetwork.cz')
@section('content')
<h1 class="text-center mb-4">Jednoduchý redakční systém v Laravel</h1>
@forelse ($articles as $article)
<article class="article mb-5">
<header>
<h2>
<a href="{{ route('article.show', ['article' => $article]) }}">{{ $article->title }}</a>
</h2>
</header>
<p class="article-content mb-1">{{ $article->description }}</p>
<footer>
<p class="small text-secondary">
<i class="fa fa-calendar"></i> Naposledy upraveno {{ $article->updated_at->diffForHumans() }}
</p>
</footer>
</article>
@empty
<p>Zatím se zde nenachází žádné články.</p>
@endforelse
@endsection
Pokud si nyní otevřeme hlavní stránku přes odkaz v menu nebo při
zadání URL adresy naší aplikace (v případě vestavěného web serveru
http://127.0.0.1:8000/), uvidíme výpis nejnovějších článků
spolu s odkázáním na ně a jejich datem poslední úpravy:

Tímto jsme dokončili vylepšování našeho projektu. Pokud se vám něco nepodařilo, můžete si stáhnout projekt z přiloženého archivu níže nebo se zeptat v komentářích pod článkem.
V následujícím kvízu, Kvíz - Mix, práce s datem a Blade direktivy v Laravel, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 93x (52.33 MB)
Aplikace je včetně zdrojových kódů v jazyce PHP
