Úvodní stránka blogu
Nyní si vytvoříme úvodní stránku zobrazující poslední příspěvky.
Než začneme, je zapotřebí znát alespoň základy návrhového vzoru Model-View-Presenter (podobné jako MVC):
- Model – vrstva pracující s daty. Je kompletně oddělena od zbytku aplikace. Komunikuje pouze s presenterem.
- View – front-end vrstva. Vykresluje požadovaná data pomocí šablon a zobrazuje je uživateli.
- Presenter (nebo Controller) – propojovací vrstva. Presenter propojuje Model a View. Zpracovává požadavky, dotazuje se Modelu na data a vrací je zpět do View.
V případě jednoduchých aplikací, jako bude náš blog, budou celou modelovou vrstvu tvořit jenom dotazy do databáze – na to zatím žádný extra kód nepotřebujeme. Pro začátek si tedy vytvoříme jenom presentery a šablony. V Nette má každý presenter své vlastní šablony, takže je budeme vytvářet zároveň.
Vytvoření databáze pomocí Admineru
Pro ukládání dat použijeme MySQL databázi, protože je nejvíce rozšířená mezi programátory webových aplikací. Pokud ji však použít nechcete, klidně si zvolte databázi dle vlastního uvážení.
Nyní si připravíme databázovou strukturu, kde budou uloženy články našeho blogu. Začneme velmi jednoduše – vytvoříme si pouze jednu tabulku pro příspěvky.
Pro vytvoření databáze si můžeme stáhnout Adminer, nebo jiný váš oblíbený nástroj pro správu databází.
Otevřeme si Adminer a vytvoříme novou databázi s názvem quickstart
.
Vytvoříme novou tabulku s názvem posts
a s těmito sloupci:
id
int, zaškrtneme na autoincrement (AI)title
varchar, length 255content
textcreated_at
timestamp
Výsledná struktura by měla vypadat takto:
CREATE TABLE `posts` (
`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`title` varchar(255) NOT NULL,
`content` text NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB CHARSET=utf8;
Je opravdu důležité použít úložiště InnoDB. Za chvilku si ukážeme proč. Prozatím ji jednoduše vyberte a klikněte na uložit.
Než vytvoříme možnost přidávat články do databáze pomocí aplikace, přidejte několik vzorových článků na blogu ručně.
INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES
(1, 'Article One', 'Lorem ipusm dolor one', CURRENT_TIMESTAMP),
(2, 'Article Two', 'Lorem ipsum dolor two', CURRENT_TIMESTAMP),
(3, 'Article Three', 'Lorem ipsum dolor three', CURRENT_TIMESTAMP);
Připojení k databázi
Nyní, když je již databáze vytvořena a máme v ní uloženo pár článků, je ten správný čas zobrazit je na naší krásné nové stránce.
Prvně musíme aplikaci říct, jakou databázi má použít. Připojení k databázi nastavíme v souboru
config/common.neon
pomocí DSN a přihlašovacích údajů. Mělo
by to vypadat nějak takto:
database:
dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
user: *zde vložte jméno uživatele*
password: *zde vložte heslo k databázi*
Při editování tohoto souboru dávejte pozor na odsazení řádků. Formát NEON akceptuje jak odsazení pomocí mezer, tak odsazení pomocí tabulátorů, ale ne obojí zároveň. Výchozí konfigurační soubor ve Web Projectu využívá tabulátory.
Předání databázového spojení
Presenter HomePresenter
, který se bude starat o výpis článků, potřebuje připojení k databázi. Pro jeho
získání využijeme konstruktor, který bude vypadat takto:
<?php
namespace App\UI\Home;
use Nette;
final class HomePresenter extends Nette\Application\UI\Presenter
{
public function __construct(
private Nette\Database\Explorer $database,
) {
}
// ...
}
Načítání příspěvků z databáze
Nyní načteme příspěvky z databáze a pošleme je do šablony, která je následně vykreslí jako HTML kód. Pro tohle je určena takzvaná render metoda:
public function renderDefault(): void
{
$this->template->posts = $this->database
->table('posts')
->order('created_at DESC')
->limit(5);
}
Presenter nyní obsahuje jednu renderovací metodu renderDefault()
, která předává data z databáze do
šablony (View). Šablony jsou umístěny v app/UI/{PresenterName}/{viewName}.latte
, takže v tomto případě je
šablona umístěna v app/UI/Home/default.latte
. V šabloně nyní bude k dispozici proměnná $posts
,
ve které jsou příspěvky získané z databáze.
Šablona
Pro celou webovou stránku máme k dispozici hlavní šablonu (která se jmenuje layout, obsahuje hlavičku, styly, patičku,…) a dále konkrétní šablony pro každý pohled (View) (např. pro zobrazení příspěvků na blogu), které mohou přepsat některé části hlavní šablony.
Ve výchozím stavu je layout šablona umístěna v app/UI/@layout.latte
a obsahuje:
...
{include content}
...
Zápis {include content}
vkládá do hlavní šablony blok s názvem content
. Ten budeme definovat
v šablonách jednotlivých pohledů (View). V našem případě soubor Home/default.latte
upravíme
následovně:
{block content}
Hello World
{/block}
Tímto jsme nadefinovali blok content, který bude vložen do
hlavního layoutu. Pokud opět obnovíme prohlížeč, uvidíme stránku s textem „Hello World“ (ve zdrojovém kódu
i s HTML hlavičkou a patičkou definovanou v @layout.latte
).
Pojďme zobrazit příspěvky z blogu – šablonu upravíme následovně:
{block content}
<h1>Můj blog</h1>
{foreach $posts as $post}
<div class="post">
<div class="date">{$post->created_at|date:'F j, Y'}</div>
<h2>{$post->title}</h2>
<div>{$post->content|truncate:256}</div>
</div>
{/foreach}
{/block}
Pokud obnovíme prohlížeč, uvidíme výpis všech příspěvků. Výpis zatím není moc hezký, ani barevný, proto
můžeme do souboru www/css/style.css
přidat pár CSS stylů a zalinkovat jej v layoutu:
...
<link rel="stylesheet" href="{$basePath}/css/style.css">
</head>
...
Značka {foreach}
iteruje přes všechny příspěvky, které jsme předali šabloně v proměnné
$posts
, a pro každý vykreslí daný kus HTML. Chová se přesně jako PHP kód.
Zápisu |date:
říkáme filtr. Filtry jsou určeny k formátování výstupu. Tento konkrétní filtr převádí
datum (např. 2013-04-12
) na jeho čitelnější podobu (April 12, 2013
). Filtr |truncate
ořízne řetězec na uvedenou maximální délku a v případě, že řetězec zkrátí, přidá na konec trojtečku. Jelikož
se jedná o náhled, nemá smysl zobrazovat celý obsah článku. Další výchozí filtry najdeme v dokumentaci a nebo si můžeme vytvořit vlastní, když je to
potřeba.
Ještě jedna věc. Předchozí kód můžeme zkrátit a zjednodušit. Toho docílíme záměnou Latte tagů za n:atributy:
{block content}
<h1>Můj blog</h1>
<div n:foreach="$posts as $post" class="post">
<div class="date">{$post->created_at|date:'F j, Y'}</div>
<h2>{$post->title}</h2>
<div>{$post->content|truncate:256}</div>
</div>
{/block}
Atribut n:foreach
obaluje div blokem foreach (funguje naprosto stejně jako předchozí kód).
Shrnutí
Nyní máme velmi jednoduchou MySQL databázi s pár příspěvky. Aplikace se připojuje k této databázi a vypisuje jednoduchý seznam těchto příspěvků do šablony.