Vlastní blog v Laravel: Zobrazení článku
Aktualizováno pro Laravel 10
Doteď jsme se zabývali především CRUD operacemi, tedy pro práci s články. Nicméně stále nám chybí zobrazení samotného článku, které si probereme v tomto díle.
Metoda pro zobrazení
Poslední metoda v Http/Controllers/PostController.php
, která nám schází upravit, je show()
:
public function show(Post $post)
{
return view('posts.post', compact('post'));
}
Stejně jako v předchozích díle, i zde pro ulehčení využiji rovnou explicitní binding a vytáhnu si celý článek, který pak předám do šablony.
Relace pro autora a kategorii
Ve článku budeme chtít určitě zobrazit i jeho autora a kategorii. Díky tomu, že jsme si hned na začátku vytvořili v tabulce posts
sloupce user_id
a category_id
, tak jsme si definovali vztah 1:n. Tedy že jeden uživatel/kategorie může mít mnoho článků, ale obráceně článek může mít pouze jednoho uživatele a kategorii. Více informací o relacích najdete v tomto seriálu.
Jedná se o nejjednodušší vazbu, kdy využijeme metodu belongsTo()
. Jako první si upravíme model app/Models/Post.php
, kde si přidáme novou metodu:
public function user()
{
return $this->belongsTo(User::class);
}
V tomto případě se Eloquent pokusí najít User
model, který má id
shodující se s hodnotou ve sloupci user_id
v modelu Post
. Eloquent určuje cizí klíč na základě názvu relační metody (tedy v našem případě je to user
), poté přidá příponu _
a nakonec následuje název primárního klíče z rodičovského modelu. Ve výsledku tedy Eloquent předpokládá, že cizí klíč na tabulku users
bude user_id
.
Laravel je však v tomto velmi flexibilní a v případě, že vaše relace nenásleduje tyto konvence, můžete jako druhý argument přidat vlastní cizí klíč:
public function user()
{
return $this->belongsTo(User::class, 'jiny_cizi_klic');
}
Pokud váš rodičovský model nepoužívá sloupec id
jako primární klíč nebo potřebujete svázat model s jiným sloupcem, pak můžete využít třetí argument metody belongsTo
pro specifikování vlastního rodičovského klíče:
public function user()
{
return $this->belongsTo(User::class, 'jiny_cizi_klic', 'rodicovsky_klic');
}
Úplně to samé pak platí pro model kategorie, kdy si do modelu Post
přidáme novou metodu:
public function category()
{
return $this->belongsTo(Category::class);
}
Šablona
Pro jednoduchost zde nebude žádná větší logika a vzhled uděláme co nejjednodušší. Vytvoříme si novou šablonu resources/views/posts/post.blade.php
:
@extends('layouts.app')
@section('title', $post->title)
@section('content')
<div class="py-12">
<h1 class="text-2xl font-semibold mb-4">{{ $post->title }}</h1>
<p>Autor: {{ $post->user->name }}</p>
<p>Kategorie: {{ $post->category->name }}</p>
<p>Vytvořeno: {{ $post->created_at->format('d.m.Y H:i') }}</p>
<br>
{{ $post->content }}
</div>
@endsection
Do sekce title
jsem přidal název článku abychom při načtení webové stránky měli v záhlaví rovnou název článku a ne výchozí text "Můj blog", id článku či něco podobného.
U autora a kategorie jsem využil vazeb, které jsme si před chvilkou vytvořili v modelu Post
. Díky této syntaxi můžete libovolně přecházet do vazeb modelu. Jedná se o tzv. "lazy loading" a Laravel získává data uživatele jen tehdy, když se pokusíte přistoupit k vlastnosti modelu User
. V praxi to znamená, že Laravel vykoná další dotaz na databázi, aby získal uživatele pro tento článek, když se pokusíte přistoupit k user
. Po získání uživatele můžete přistupovat k jeho vlastnostem, jako je v našem případě name
. Stejná logika pak platí i na kategorii.
Jako poslední zmíním formátování data a času. Když jsme hned na začátku seriálu vytvářeli migraci pro tabulku post
tak jsme si vytvořili i dva nové timestamp
sloupce created_at
a update_at
:
$table->timestamps();
// ktery je jen sugar syntax pro
$this->timestamp('created_at', $precision)->nullable();
$this->timestamp('updated_at', $precision)->nullable();
Laravel automaticky převádí tyto sloupce na instanci typu Carbon
. Carbon je PHP knihovna, která usnadňuje práci s daty a časy. Je založena na nativní PHP třídě DateTime
, ale přidává mnoho užitečných funkcí a je mnohem příjemnější na použití.
Některé z funkcí Carbonu zahrnují:
- Snadnou manipulaci s daty: Carbon poskytuje metody pro přidávání a odečítání jednotek času (například dnů, měsíců, let, hodin, minut atd.) od daného data.
$now = Carbon::now();
$tomorrow = $now->addDay();
$lastWeek = $now->subWeek();
- Lidsky čitelný formát: Carbon umožňuje snadné formátování dat a časů pro výstup lidsky čitelným způsobem.
echo $now->diffForHumans(); // "1 second ago"
- Lokalizace: Carbon podporuje lokalizaci, takže můžete formátovat data a časy pro různé jazyky a kultury.
- Převod mezi časovými pásmy: Carbon usnadňuje převod dat a časů mezi různými časovými pásmy.
- Porovnání dat: Carbon poskytuje metody pro porovnání dvou dat a zjištění, které je dřívější nebo pozdější.
- Převod na a z timestampu: Carbon umožňuje snadné převádění mezi objekty Carbon a Unix timestampy.
Pokud máte v tabulce sloupec podobného typu datetime
, pak ho můžete automaticky převádět do instance Carbonu pomocí přetypování v modelu Post
:
protected $casts = [
'valid_date' => 'datetime',
];
Odkaz v seznamu článků
Na závěr si ještě upravíme tabulku se seznamem všech článku resources/views/posts/index.blade.php
kde si přidáme odkaz na daný článek:
<tbody class="bg-white">
@foreach ($posts as $post)
<tr>
<td class="border-b border-slate-100 dark:border-slate-700 p-4 pl-8 text-slate-500 dark:text-slate-400">
<a class="underline" href="{{ route('posts.show', $post->id) }}">{{ $post->title }}</a>
</td>
<td class="border-b border-slate-100 dark:border-slate-700 p-4 pl-8 text-slate-500 dark:text-slate-400">{{ $post->created_at }}</td>
<td class="border-b border-slate-100 dark:border-slate-700 p-4 pl-8 text-slate-500 dark:text-slate-400">{{ $post->updated_at }}</td>
<td class="border-b border-slate-100 dark:border-slate-700 p-4 pl-8 text-slate-500 dark:text-slate-400">
<a href="{{ route('posts.edit', $post->id) }}" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Editovat</a>
<form action="{{ route('posts.destroy', $post->id) }}" method="POST" class="inline">
@csrf
@method('DELETE')
<button type="submit" class="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded">Smazat</button>
</form>
</td>
</tr>
@endforeach
</tbody>
Závěr
A to je poslední díl této série. V případě zájmu můžu pokračovat v rozvíjení tohoto blogu a přidat registraci/přihlašování, další funkcionality, vylepšit vzhled a mnoho dalšího. Dejte vědět o co by jste měli zájem a zkusím něco sepsat.
Není vám něco jasné, nefunguje nebo mám někde chybu? Napište do komentářů!
Zdrojové kódy pro tento díl naleznete na GitHubu
Seriál