Pagina principale del blog

Creiamo la pagina principale che mostra i vostri articoli più recenti.

Prima di cominciare dovreste conoscere almeno le basi del design pattern Model-View-Presenter (simile a MVC):

  • Model – il livello che lavora con i dati. È completamente separato dal resto dell'applicazione. Comunica solo con il presenter.
  • View – il livello di front-end. Renderizza i dati richiesti usando i template e li mostra all'utente.
  • Presenter (o Controller) – il livello di collegamento. Il presenter collega il Model e la View. Elabora le richieste, chiede i dati al Model e poi li passa alla View.

Nel caso di un'applicazione semplice come il nostro blog, tutto il livello del model sarà composto solo da query al database: per ora non ci serve altro codice PHP. Per cominciare creeremo quindi solo presenter e template. In Nette ogni presenter ha i propri template, quindi li creeremo insieme.

Creazione del database con Adminer

Per salvare i dati useremo un database MySQL, perché è la scelta più diffusa tra gli sviluppatori web. Se però non volete usarlo, scegliete pure il database che preferite.

Prepariamo la struttura del database che conserverà gli articoli del nostro blog. Possiamo cominciare in modo molto semplice, con una sola tabella per gli articoli.

Per creare il database possiamo scaricare Adminer, oppure usare un altro strumento di gestione dei database che preferite.

Apriamo Adminer e creiamo un nuovo database chiamato quickstart.

Create una nuova tabella chiamata posts e aggiungete queste colonne:

  • id int, spuntate autoincrement (AI)
  • title varchar, lunghezza 255
  • content text
  • created_at timestamp

Dovrebbe apparire così:

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;

È molto importante usare il motore di storage InnoDB. Il motivo lo vedrete più avanti. Per ora sceglietelo e cliccate Salva.

Provate ad aggiungere a mano qualche articolo di esempio prima di realizzare l'aggiunta di nuovi articoli direttamente dalla nostra applicazione.

INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES
(1,	'Primo articolo',	'Lorem ipsum dolor uno',	CURRENT_TIMESTAMP),
(2,	'Secondo articolo',	'Lorem ipsum dolor due',	CURRENT_TIMESTAMP),
(3,	'Terzo articolo',	'Lorem ipsum dolor tre',	CURRENT_TIMESTAMP);

Connessione al database

Ora che il database è creato e ci abbiamo dentro qualche articolo, è il momento giusto per mostrarli sulla nostra nuovissima pagina.

Per prima cosa dobbiamo dire alla nostra applicazione quale database usare. La configurazione della connessione al database si imposta nel file config/common.neon con il DSN e le credenziali. Dovrebbe apparire più o meno così:

database:
	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
	user: *inserite qui il vostro nome utente*
	password: *inserite qui la password del vostro database*

Fate attenzione all'indentazione quando modificate questo file. Il formato NEON accetta sia spazi sia tabulazioni, ma non entrambi insieme. Il file di configurazione predefinito del Web Project usa le tabulazioni.

Iniezione della connessione al database

Il presenter HomePresenter, che elencherà gli articoli, ha bisogno della connessione al database. Per riceverla useremo il costruttore, così:

<?php
namespace App\Presentation\Home;

use Nette;

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

	// ...
}

Caricare gli articoli dal database

Prendiamo ora gli articoli dal database e passiamoli al template, che poi renderizzerà il codice HTML. A questo serve il cosiddetto metodo render:

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

Il presenter ha ora un metodo render renderDefault(), che passa i dati dal database al template (View). I template si trovano in app/Presentation/{NomePresenter}/{nomeVista}.latte, quindi in questo caso il template si trova in app/Presentation/Home/default.latte. Nel template è ora disponibile una variabile chiamata $posts, che contiene gli articoli presi dal database.

Template

Per tutto il sito abbiamo un template principale (chiamato layout, che contiene intestazione, stili, piè di pagina, …) e template specifici per ogni vista (per esempio per mostrare gli articoli del blog), che possono sovrascrivere parti del template principale.

Per impostazione predefinita il template di layout si trova in app/Presentation/@layout.latte e contiene:

...
{include content}
...

Il tag {include content} inserisce nel template principale un blocco chiamato content. Questo blocco lo definiremo nei template delle singole viste. Nel nostro caso modificheremo il file Home/default.latte così:

{block content}
	Hello World
{/block}

Questo definisce il blocco content, che verrà inserito nel layout principale. Se aggiornate di nuovo il browser, vedrete una pagina con il testo “Hello World” (nel codice sorgente anche con l'intestazione e il piè di pagina HTML definiti in @layout.latte).

Mostriamo gli articoli del blog: modifichiamo il template così:

{block content}
	<h1>Il mio blog</h1>

	{foreach $posts as $post}
	<div class="post">
		<div class="date">{$post->created_at|date:'j. n. Y'}</div>

		<h2>{$post->title}</h2>

		<div>{$post->content|truncate:256}</div>
	</div>
	{/foreach}
{/block}

Se aggiornate il browser, vedrete l'elenco degli articoli del vostro blog. L'elenco non è ancora molto elegante né colorato, quindi aggiungete pure qualche bello stile CSS al file www/css/style.css e collegatelo nel layout:

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

Il tag {foreach} itera su tutti gli articoli passati al template nella variabile $posts e per ognuno mostra un pezzo di codice HTML. Si comporta proprio come il codice PHP.

La notazione |date: si chiama filtro. I filtri servono a formattare l'output. Questo filtro converte una data (per esempio 2013-04-12) nella sua forma più leggibile (12. 4. 2013). Il filtro |truncate accorcia la stringa alla lunghezza massima indicata e, se la stringa viene accorciata, aggiunge alla fine i puntini di sospensione (…). Poiché si tratta di un'anteprima, non ha senso mostrare tutto il contenuto dell'articolo. Gli altri filtri predefiniti li trovate nella documentazione, oppure potete crearne di vostri se serve.

Ancora una cosa. Possiamo rendere il codice precedente più breve e più semplice. Lo otteniamo sostituendo i tag di Latte con gli n:attributi:

{block content}
	<h1>Il mio blog</h1>

	<div n:foreach="$posts as $post" class="post">
		<div class="date">{$post->created_at|date:'j. n. Y'}</div>

		<h2>{$post->title}</h2>

		<div>{$post->content|truncate:256}</div>
	</div>
{/block}

L'attributo n:foreach avvolge il blocco div con un ciclo foreach (funziona esattamente come il codice precedente).

Abbiamo ora un database MySQL molto semplice con qualche articolo. L'applicazione si connette a questo database e mostra in un template un semplice elenco di questi articoli.