A blog kezdőlapja

Most létrehozzuk a kezdőlapot, amely a legutóbbi bejegyzéseket jeleníti meg.

Mielőtt elkezdenénk, ismerni kell legalább a Model-View-Presenter tervezési minta alapjait (hasonlóan az MVC-hez ((Model-View-Controller))):

  • Modell – az adatokkal dolgozó réteg. Teljesen elkülönül az alkalmazás többi részétől. Csak a presenterrel kommunikál.
  • View – a front-end réteg. A kért adatokat sablonok segítségével jeleníti meg, és megjeleníti a felhasználónak.
  • Presenter (vagy Controller) – az összekötő réteg. A Presenter összeköti a Modellt és a View-t. Feldolgozza a kéréseket, lekérdezi az adatokat a Modelltől, és visszaküldi azokat a View-nak.

Egyszerű alkalmazások esetén, mint a mi blogunk, az egész modell réteget csak adatbázis-lekérdezések alkotják – ehhez egyelőre nincs szükségünk extra kódra. Kezdetnek tehát csak presentereket és sablonokat hozunk létre. A Nette-ben minden presenternek saját sablonjai vannak, így ezeket egyszerre fogjuk létrehozni.

Adatbázis létrehozása az Adminer segítségével

Az adatok tárolására MySQL adatbázist fogunk használni, mivel ez a legelterjedtebb a webalkalmazás-fejlesztők körében. Ha azonban nem szeretné használni, nyugodtan válasszon saját belátása szerint adatbázist.

Most előkészítjük az adatbázis struktúráját, ahol a blogunk cikkei lesznek tárolva. Nagyon egyszerűen kezdünk – csak egy táblát hozunk létre a bejegyzésekhez.

Az adatbázis létrehozásához letölthetjük az Adminer-t, vagy bármely más kedvenc adatbázis-kezelő eszközünket.

Nyissuk meg az Adminert, és hozzunk létre egy új adatbázist quickstart néven.

Hozzunk létre egy új posts nevű táblát a következő oszlopokkal:

  • id int, jelöljük be az autoincrement-et (AI)
  • title varchar, length 255
  • content text
  • created_at timestamp

Az eredményül kapott struktúrának így kell kinéznie:

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;

Nagyon fontos az InnoDB tároló használata. Hamarosan megmutatjuk, miért. Egyelőre egyszerűen válassza ki, és kattintson a mentésre.

Mielőtt létrehoznánk a cikkek adatbázisba való hozzáadásának lehetőségét az alkalmazáson keresztül, adjon hozzá néhány minta cikket a bloghoz manuálisan.

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);

Csatlakozás az adatbázishoz

Most, hogy az adatbázis már létre van hozva, és van benne néhány cikkünk, itt az ideje megjeleníteni őket a gyönyörű új oldalunkon.

Először meg kell mondanunk az alkalmazásnak, hogy melyik adatbázist használja. Az adatbázis-kapcsolatot a config/common.neon fájlban állítjuk be DSN ((Data Source Name)) és bejelentkezési adatok segítségével. Valahogy így kell kinéznie:

database:
	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
	user: *itt adja meg a felhasználónevet*
	password: *itt adja meg az adatbázis jelszavát*

Ennek a fájlnak a szerkesztésekor ügyeljen a sorok behúzására. A NEON formátum elfogadja mind a szóközökkel, mind a tabulátorokkal történő behúzást, de nem mindkettőt egyszerre. A Web Project alapértelmezett konfigurációs fájlja tabulátorokat használ.

Adatbázis-kapcsolat átadása

A HomePresenter presenternek, amely a cikkek listázásáért felel, szüksége van adatbázis-kapcsolatra. Ennek megszerzéséhez a konstruktort használjuk, amely így fog kinézni:

<?php
namespace App\Presentation\Home;

use Nette;

final class HomePresenter extends Nette\Application\UI\Presenter
{
	public function __construct(
		private Nette\Database\Explorer $database,
	) {
	}

	// ...
}

Bejegyzések betöltése az adatbázisból

Most betöltjük a bejegyzéseket az adatbázisból, és elküldjük őket a sablonnak, amely azután HTML kódként jeleníti meg őket. Erre szolgál az úgynevezett render metódus:

public function renderDefault(): void
{
	$this->template->posts = $this->database
		->table('posts')
		->order('created_at DESC')
		->limit(5);
}

A presenter most egy renderelő metódust tartalmaz, a renderDefault()-t, amely adatokat ad át az adatbázisból a sablonnak (View). A sablonok az app/Presentation/{PresenterName}/{viewName}.latte helyen találhatók, tehát ebben az esetben a sablon az app/Presentation/Home/default.latte helyen van. A sablonban most elérhető lesz a $posts változó, amelyben az adatbázisból lekérdezett bejegyzések találhatók.

Sablon

Az egész weboldalhoz rendelkezésünkre áll egy fő sablon (amelyet layout-nak neveznek, tartalmazza a fejlécet, stílusokat, láblécet,…) és továbbá konkrét sablonok minden nézethez (View) (pl. a blogbejegyzések megjelenítéséhez), amelyek felülírhatják a fő sablon egyes részeit.

Alapértelmezés szerint a layout sablon az app/Presentation/@layout.latte helyen található, és tartalmazza:

...
{include content}
...

A {include content} beilleszti a fő sablonba a content nevű blokkot. Ezt az egyes nézetek (View) sablonjaiban fogjuk definiálni. Esetünkben az Home/default.latte fájlt a következőképpen módosítjuk:

{block content}
	Hello World
{/block}

Ezzel definiáltuk a blokkot content, amely be lesz illesztve a fő layoutba. Ha újra frissítjük a böngészőt, egy oldalt látunk a “Hello World” szöveggel (a forráskódban az @layout.latte-ban definiált HTML fejléccel és lábléccel együtt).

Jelenítsük meg a blogbejegyzéseket – a sablont a következőképpen módosítjuk:

{block content}
	<h1>Blogom</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}

Ha frissítjük a böngészőt, látni fogjuk az összes bejegyzés listáját. A lista egyelőre nem túl szép, sem színes, ezért a www/css/style.css fájlba hozzáadhatunk néhány CSS stílusokat, és belinkelhetjük a layoutban:

	...
	<link rel="stylesheet" href="{$basePath}/css/style.css">
</head>
...

A {foreach} tag iterál az összes bejegyzésen, amelyeket a $posts változóban adtunk át a sablonnak, és mindegyikhez megjeleníti az adott HTML darabot. Pontosan úgy viselkedik, mint a PHP kód.

A |date: írásmódot szűrőnek nevezzük. A szűrők a kimenet formázására szolgálnak. Ez a konkrét szűrő átalakítja a dátumot (pl. 2013-04-12) annak olvashatóbb formájára (April 12, 2013). A |truncate szűrő levágja a stringet a megadott maximális hosszúságra, és ha a stringet lerövidíti, a végére három pontot tesz. Mivel ez egy előnézet, nincs értelme a teljes cikk tartalmát megjeleníteni. További alapértelmezett szűrőket megtalálhatók a dokumentációban, vagy létrehozhatunk sajátokat, ha szükséges.

Még egy dolog. Az előző kódot lerövidíthetjük és egyszerűsíthetjük. Ezt a Latte tagek n:attribútumokra cserélésével érhetjük el:

{block content}
	<h1>Blogom</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}

Az n:foreach attribútum a div blokkot foreach-csel veszi körül (teljesen ugyanúgy működik, mint az előző kód).

Összegzés

Most van egy nagyon egyszerű MySQL adatbázisunk néhány bejegyzéssel. Az alkalmazás csatlakozik ehhez az adatbázishoz, és egyszerű listát jelenít meg ezekről a bejegyzésekről a sablonban.