Головна сторінка блогу
Давайте створимо головну сторінку, на якій відображатимуться ваші останні пости.
Перш ніж ми почнемо, ви маєте знати хоча б деякі основи патерну проєктування Model-View-Presenter (аналогічного MVC)):
- Модель – рівень маніпулювання даними. Він повністю відокремлений від іншої частини додатка і спілкується тільки з презентерами.
- Вид (або _Представлення_) – зовнішній рівень визначення. Він відображає запитувані дані користувачеві за допомогою шаблонів.
- Презентер (або _Контролер_) – рівень з'єднання. Презентер з'єднує модель і вигляд. Обробляє запити, запитує дані у моделі і потім передає їх поточному поданню.
У разі дуже простого застосунку, такого як наш блог, шар Model фактично складатиметься тільки із запитів до самої бази даних – нам не потрібен додатковий PHP-код для цього. Нам потрібно створити тільки шари Presenter і View. У Nette у кожного презентера є свої подання, тому ми продовжимо роботу з ними обома одночасно.
Створення бази даних за допомогою Adminer
Для зберігання даних ми будемо використовувати базу даних MySQL, оскільки це найбільш поширений вибір серед веб-розробників. Але якщо вам це не подобається, не соромтеся використовувати базу даних за своїм вибором.
Давайте підготуємо базу даних, у якій зберігатимуться записи нашого блогу. Почнемо з однієї таблиці для постів.
Для створення бази даних ми можемо завантажити Adminer, або ви можете використати інший інструмент для управління базами даних.
Давайте відкриємо Adminer і створимо нову базу даних під назвою
quickstart
.
Створіть нову таблицю з іменем posts
і додайте до неї ці
стовпці:
id
int, натисніть на автоінкремент (AI)title
varchar, довжина 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. Причину ви побачите пізніше. Поки що просто створіть все за інструкцією і натисніть кнопку Зберегти. Або використовуйте повний код створення таблиці та кнопку SQL-запит в Adminer.
Спробуйте додати кілька записів до блогу, перш ніж ми реалізуємо можливість додавання нових записів безпосередньо з нашого застосунку.
INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES
(1, 'Статья первая', 'Lorem ipusm dolor one', CURRENT_TIMESTAMP),
(2, 'Статья вторая', 'Lorem ipsum dolor two', CURRENT_TIMESTAMP),
(3, 'Статья третья', 'Lorem ipsum dolor three', CURRENT_TIMESTAMP);
Підключення до бази даних
Тепер, коли база даних створена і в ній є кілька постів, саме час відобразити їх на нашій новій блискучій сторінці.
По-перше, нам потрібно повідомити нашому додатку, яку базу даних
використовувати. Конфігурація підключення до бази даних зберігається
у файлі config/common.neon
. Встановіть з'єднання DSN і свої облікові дані. Це має
виглядати так:
database:
dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
user: *укажите здесь имя пользователя*
password: *укажите здесь пароль*
Пам'ятайте про відступи під час редагування цього файлу. Формат NEON приймає і пробіли, і табуляцію, але не те й інше разом! У файлі конфігурації у веб-проекті за замовчуванням використовується табуляція.
Впровадження підключення до бази даних
Презентер (розташований у app/UI/Home/HomePresenter.php
), який буде
перераховувати статті, потребує підключення до бази даних. Для цього
змініть конструктор таким чином:
<?php
namespace App\UI\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);
}
Тепер у презентері є один метод рендерингу renderDefault()
, який
передає дані в подання під назвою default
. Шаблони презентера можна
знайти в app/UI/{PresenterName}/{viewName}.latte
, тому в даному випадку шаблон
буде розташований в app/UI/Home/default.latte
. У шаблоні тепер доступна
змінна $posts
, яка містить пости з бази даних.
Шаблон
Існує загальний шаблон для всієї сторінки (називається layout (макет), із заголовком, таблицями стилів, нижнім колонтитулом тощо), а також специфічні шаблони для кожного виду (наприклад, для відображення списку записів блогу), які можуть перевизначати деякі частини шаблону макета.
За замовчуванням шаблон макета розташовується у файлі
app/UI/@layout.latte
, який містить:
...
{include content}
...
{include content}
вставляє блок з ім'ям content
в основний шаблон.
Ви можете визначити його в шаблонах кожного подання. У нашому випадку
ми відредагуємо файл app/UI/Home/default.latte
таким чином:
{block content}
Привет, мир!
{/block}
Він визначає блок контенту, який
буде вставлено в макет. Якщо ви оновите браузер, то побачите сторінку з
текстом “Привіт, світ!” (у вихідному коді також із HTML заголовком і
колонтитулом, визначеними в @layout.latte
).
Давайте відобразимо записи блогу – для цього відредагуємо шаблон таким чином:
{block content}
<h1 n:block="title">Мой блог</h1>
{foreach $posts as $post}
<div class="post">
<div class="date">{$post->created_at|date:'j.m.Y'}</div>
<h2>{$post->title}</h2>
<div>{$post->content|truncate:256}</div>
</div>
{/foreach}
{/block}
Якщо ви оновите браузер, ви побачите список записів вашого блогу.
Список не дуже вигадливий або барвистий, тому не соромтеся додати
трохи блискучого CSS у
www/css/style.css
, а потім вставте посилання на цей файл у макет (файл
@layout.latte
):
...
<link rel="stylesheet" href="{$basePath}/css/style.css">
</head>
...
Тег {foreach}
перебирає всі пости, передані шаблону у змінній
$posts
, і виводить фрагмент HTML-коду для кожного поста. Точно так
само, як це робиться в PHP-коді.
Функція |date
називається фільтром. Фільтри використовуються
для форматування виведення. Цей конкретний фільтр перетворює дату
(наприклад, 2013-04-12
) у більш читабельну форму (12.04.2013
).
Фільтр |truncate
усікає рядок до вказаної максимальної довжини і
додає три крапки в кінець, якщо рядок усічений. Оскільки це попередній
перегляд, немає сенсу відображати повний зміст статті. Інші фільтри за
замовчуванням можна знайти в документації
або ви можете створити свої власні, якщо це необхідно.
І ще одне. Ми можемо зробити код трохи коротшим і, отже, простішим. Ми можемо замінити теги Latte на n:attributes таким чином:
{block content}
<h1>My 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}</div>
</div>
{/block}
n:foreach
просто обгортає div блоком foreach (він робить те саме,
що й попередній блок коду).
Підіб'ємо підсумок
У нас є дуже проста база даних MySQL з деякими записами в блозі. Додаток підключається до бази даних і відображає простий список постів.