Начална страница на блога
Сега ще създадем начална страница, показваща последните публикации.
Преди да започнем, е необходимо да познавате поне основите на дизайнерския модел Model-View-Presenter (подобен на MVC):
- Модел – слой, работещ с данни. Той е напълно отделен от останалата част на приложението. Комуникира само с презентера.
- Изглед – фронт-енд слой. Рендира изискваните данни с помощта на шаблони и ги показва на потребителя.
- Presenter (или Контролер) – свързващ слой. Presenter свързва Модела и Изгледа. Обработва заявките, изисква данни от Модела и ги връща обратно на Изгледа.
В случай на прости приложения, като нашия блог, целият моделен слой ще се състои само от заявки към базата данни – засега не се нуждаем от допълнителен код за това. За начало ще създадем само презентери и шаблони. В Nette всеки презентер има свои собствени шаблони, така че ще ги създаваме едновременно.
Създаване на база данни с помощта на Adminer
За съхраняване на данни ще използваме MySQL база данни, тъй като тя е най-разпространената сред програмистите на уеб приложения. Ако обаче не искате да я използвате, спокойно изберете база данни по ваш избор.
Сега ще подготвим структурата на базата данни, където ще се съхраняват статиите на нашия блог. Ще започнем много просто – ще създадем само една таблица за публикациите.
За създаване на базата данни можем да изтеглим Adminer или друг ваш любим инструмент за управление на бази данни.
Отваряме Adminer и създаваме нова база данни с име quickstart
.
Създаваме нова таблица с име posts
и със следните колони:
id
int, отметнете autoincrement (AI)title
varchar, length 255content
textcreated_at
timestamp
Получената структура трябва да изглежда така:

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;
Наистина е важно да използвате хранилище InnoDB. След малко ще покажем защо. Засега просто го изберете и кликнете върху запазване.
Преди да създадем възможност за добавяне на статии в базата данни с помощта на приложението, добавете няколко примерни статии в блога ръчно.
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);
Свързване с базата данни
Сега, когато базата данни вече е създадена и имаме запазени няколко статии в нея, е време да ги покажем на нашата красива нова страница.
Първо трябва да кажем на приложението коя база данни да използва.
Връзката с базата данни се настройва във файла config/common.neon
с
помощта на DSN и данните за вход. Трябва да
изглежда по следния начин:
database:
dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
user: *тук въведете потребителско име*
password: *тук въведете парола за базата данни*
При редактиране на този файл внимавайте с индентацията на редовете. Форматът NEON приема както индентация с интервали, така и индентация с табулации, но не и двете едновременно. Конфигурационният файл по подразбиране в Web Project използва табулации.
Предаване на връзката с базата данни
Presenter HomePresenter
, който ще се грижи за извеждането на статиите, се
нуждае от връзка с базата данни. За да я получим, ще използваме
конструктор, който ще изглежда така:
<?php
namespace App\Presentation\Home;
use Nette;
final class HomePresenter extends Nette\Application\UI\Presenter
{
public function __construct(
private Nette\Database\Explorer $database,
) {
}
// ...
}
Зареждане на публикации от базата данни
Сега ще заредим публикациите от базата данни и ще ги изпратим към шаблона, който след това ще ги рендира като HTML код. За това е предназначен така нареченият render метод:
public function renderDefault(): void
{
$this->template->posts = $this->database
->table('posts')
->order('created_at DESC')
->limit(5);
}
Presenter сега съдържа един рендиращ метод renderDefault()
, който предава
данни от базата данни към шаблона (Изглед). Шаблоните са разположени в
app/Presentation/{PresenterName}/{viewName}.latte
, така че в този случай шаблонът е
разположен в app/Presentation/Home/default.latte
. В шаблона сега ще бъде налична
променлива $posts
, в която са публикациите, получени от
базата данни.
Шаблон
За целия уеб сайт имаме на разположение главен шаблон (който се нарича лейаут, съдържа хедър, стилове, футър,…) и след това конкретни шаблони за всеки изглед (View) (например за показване на публикации в блога), които могат да презапишат някои части от главния шаблон.
По подразбиране лейаут шаблонът е разположен в
app/Presentation/@layout.latte
и съдържа:
...
{include content}
...
Записът {include content}
вмъква в главния шаблон блок с име
content
. Него ще дефинираме в шаблоните на отделните изгледи (View). В
нашия случай файлът Home/default.latte
ще променим по следния начин:
{block content}
Hello World
{/block}
С това дефинирахме блок content, който
ще бъде вмъкнат в главния лейаут. Ако отново обновим браузъра, ще видим
страница с текст “Hello World” (в изходния код също с HTML хедър и футър,
дефинирани в @layout.latte
).
Нека покажем публикациите от блога – ще променим шаблона по следния начин:
{block content}
<h1>Моят блог</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}
Ако обновим браузъра, ще видим списък с всички публикации. Списъкът
засега не е много хубав, нито цветен, затова можем да добавим към файла
www/css/style.css
няколко CSS стила и да го свържем в
лейаута:
...
<link rel="stylesheet" href="{$basePath}/css/style.css">
</head>
...
Тагът {foreach}
итерира през всички публикации, които сме предали
на шаблона в променливата $posts
, и за всяка рендира дадения HTML код.
Държи се точно като PHP код.
На записа |date:
казваме филтър. Филтрите са предназначени за
форматиране на изхода. Този конкретен филтър преобразува дата (напр.
2013-04-12
) в нейната по-четима форма (April 12, 2013
). Филтърът
|truncate
отрязва низ до посочената максимална дължина и в случай,
че низът бъде скъсен, добавя накрая три точки. Тъй като това е преглед,
няма смисъл да се показва цялото съдържание на статията. Други филтри
по подразбиране можем да намерим в
документацията или можем да създадем собствени, когато е
необходимо.
Още нещо. Предишният код можем да съкратим и опростим. Това ще постигнем чрез замяна на Latte тагове с n:атрибути:
{block content}
<h1>Моят блог</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}
Атрибутът n:foreach
обвива div блока с foreach (работи абсолютно
същото като предишния код).
Резюме
Сега имаме много проста MySQL база данни с няколко публикации. Приложението се свързва с тази база данни и извежда прост списък с тези публикации в шаблона.